blob: 4394455c7490867e49d98af71ff58a0f8301b87c [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "xfa/fxfa/fm2js/xfa_fm2jscontext.h"
8
9#include <time.h>
10
Dan Sinclair85c8e7f2016-11-21 13:50:32 -050011#include <algorithm>
12#include <memory>
13#include <vector>
14
dsinclaira52ab742016-09-29 13:59:29 -070015#include "core/fxcrt/fx_ext.h"
dsinclair43554682016-09-29 17:29:48 -070016#include "fxjs/cfxjse_arguments.h"
17#include "fxjs/cfxjse_class.h"
18#include "fxjs/cfxjse_value.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040019#include "xfa/fgas/localization/fgas_locale.h"
dsinclairdf4bc592016-03-31 20:34:43 -070020#include "xfa/fxfa/app/xfa_ffnotify.h"
dsinclaire80e9f82016-06-01 06:10:04 -070021#include "xfa/fxfa/fm2js/xfa_program.h"
dsinclair16280242016-07-21 12:03:47 -070022#include "xfa/fxfa/parser/cxfa_document.h"
dsinclair31f87402016-07-20 06:34:45 -070023#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040024#include "xfa/fxfa/parser/xfa_localevalue.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040025
Dan Sinclair1770c022016-03-14 14:14:16 -040026namespace {
27
dsinclair48d91dd2016-05-31 11:54:01 -070028const double kFinancialPrecision = 0.00000001;
29
Dan Sinclair1770c022016-03-14 14:14:16 -040030struct XFA_FMHtmlReserveCode {
31 uint32_t m_uCode;
32 const FX_WCHAR* m_htmlReserve;
33};
dsinclair48d91dd2016-05-31 11:54:01 -070034
Dan Sinclair1770c022016-03-14 14:14:16 -040035struct XFA_FMHtmlHashedReserveCode {
36 uint32_t m_uHash;
Dan Sinclair1770c022016-03-14 14:14:16 -040037 uint32_t m_uCode;
38};
39
40const XFA_FMHtmlHashedReserveCode reservesForDecode[] = {
dsinclair89ba6de2016-05-31 12:11:22 -070041 {0x00018b62, /*L"Mu",*/ 924}, {0x00019083, /*L"Nu",*/ 925},
42 {0x00019ab9, /*L"Pi",*/ 928}, {0x0001c3c1, /*L"Xi",*/ 926},
43 {0x000210ac, /*L"ge",*/ 8805}, {0x000210bb, /*L"gt",*/ 62},
44 {0x00022a51, /*L"le",*/ 8804}, {0x00022a60, /*L"lt",*/ 60},
45 {0x00022f82, /*L"mu",*/ 956}, {0x00023493, /*L"ne",*/ 8800},
46 {0x00023497, /*L"ni",*/ 8715}, {0x000234a3, /*L"nu",*/ 957},
47 {0x000239c1, /*L"or",*/ 8744}, {0x00023ed9, /*L"pi",*/ 960},
48 {0x000267e1, /*L"xi",*/ 958}, {0x00c41789, /*L"lceil",*/ 8968},
49 {0x00eef34f, /*L"thetasym",*/ 977}, {0x012d7ead, /*L"lcirc",*/ 206},
50 {0x01637b56, /*L"agrave",*/ 224}, {0x020856da, /*L"crarr",*/ 8629},
51 {0x022188c3, /*L"gamma",*/ 947}, {0x033586d3, /*L"nbsp",*/ 160},
52 {0x04f4c358, /*L"nsub",*/ 8836}, {0x0581466a, /*L"dagger",*/ 8224},
53 {0x06b1f790, /*L"oelig",*/ 339}, {0x06e490d4, /*L"Chi",*/ 935},
54 {0x0718c6a1, /*L"ETH",*/ 208}, {0x07196ada, /*L"Eta",*/ 919},
55 {0x07f667ca, /*L"Ugrave",*/ 217}, {0x083a8a21, /*L"Phi",*/ 934},
56 {0x083ac28c, /*L"Psi",*/ 936}, {0x086f26a9, /*L"Rho",*/ 929},
57 {0x089b5b51, /*L"aring",*/ 229}, {0x08a39f4a, /*L"Tau",*/ 932},
58 {0x08b6188b, /*L"THORN",*/ 222}, {0x09ce792a, /*L"icirc",*/ 238},
59 {0x09f9d61e, /*L"amp",*/ 38}, {0x09f9db33, /*L"and",*/ 8743},
60 {0x09f9db36, /*L"ang",*/ 8736}, {0x0a2e3514, /*L"cap",*/ 8745},
61 {0x0a2e58f4, /*L"chi",*/ 967}, {0x0a2e9ba8, /*L"cup",*/ 8746},
62 {0x0a4897d0, /*L"deg",*/ 176}, {0x0a6332fa, /*L"eta",*/ 951},
63 {0x0a633301, /*L"eth",*/ 240}, {0x0acc4d4b, /*L"int",*/ 8747},
64 {0x0b1b3d35, /*L"loz",*/ 9674}, {0x0b1b4c8b, /*L"lrm",*/ 8206},
65 {0x0b4fd9b1, /*L"not",*/ 172}, {0x0b845241, /*L"phi",*/ 966},
66 {0x0b84576f, /*L"piv",*/ 982}, {0x0b848aac, /*L"psi",*/ 968},
67 {0x0bb8df5e, /*L"reg",*/ 174}, {0x0bb8eec9, /*L"rho",*/ 961},
68 {0x0bb9034b, /*L"rlm",*/ 8207}, {0x0bd33d14, /*L"shy",*/ 173},
69 {0x0bd34229, /*L"sim",*/ 8764}, {0x0bd37faa, /*L"sub",*/ 8834},
70 {0x0bd37fb5, /*L"sum",*/ 8721}, {0x0bd37fb8, /*L"sup",*/ 8835},
71 {0x0bed676a, /*L"tau",*/ 964}, {0x0c07f32e, /*L"uml",*/ 168},
72 {0x0c71032c, /*L"yen",*/ 165}, {0x0c7f2889, /*L"szlig",*/ 223},
73 {0x0c8badbb, /*L"zwj",*/ 8205}, {0x10ba4dba, /*L"Egrave",*/ 200},
74 {0x10f1ea24, /*L"para",*/ 182}, {0x10f1ea37, /*L"part",*/ 8706},
75 {0x115b2337, /*L"perp",*/ 8869}, {0x12b10d15, /*L"prod",*/ 8719},
76 {0x12b10d21, /*L"prop",*/ 8733}, {0x12dfa9f4, /*L"rfloor",*/ 8971},
77 {0x12eb4736, /*L"Agrave",*/ 192}, {0x12fff2b7, /*L"pund",*/ 163},
78 {0x13fda9f2, /*L"tilde",*/ 732}, {0x1417fd62, /*L"times",*/ 215},
79 {0x154fc726, /*L"ecirc",*/ 234}, {0x165aa451, /*L"sigma",*/ 963},
80 {0x1709124a, /*L"Dagger",*/ 8225}, {0x192f78d5, /*L"iexcl",*/ 161},
81 {0x1b7ed8d7, /*L"rArr",*/ 8658}, {0x1ec88c68, /*L"rang",*/ 9002},
82 {0x1ec8a0f7, /*L"rarr",*/ 8594}, {0x1eda07f3, /*L"atilde",*/ 227},
83 {0x1f3182c4, /*L"real",*/ 8476}, {0x1fc34f8b, /*L"yacute",*/ 253},
84 {0x20d11522, /*L"acirc",*/ 226}, {0x21933a9b, /*L"rsaquo",*/ 8250},
85 {0x21f44907, /*L"uacute",*/ 250}, {0x220cca72, /*L"acute",*/ 180},
86 {0x242cded1, /*L"alefsym",*/ 8501}, {0x2655c66a, /*L"delta",*/ 948},
87 {0x269e4b4d, /*L"exist",*/ 8707}, {0x273379fa, /*L"micro",*/ 181},
88 {0x27a37440, /*L"forall",*/ 8704}, {0x2854e62c, /*L"minus",*/ 8722},
89 {0x28636f81, /*L"cedil",*/ 184}, {0x2887357b, /*L"iacute",*/ 237},
90 {0x2994d5ff, /*L"frac12",*/ 189}, {0x2994d601, /*L"frac14",*/ 188},
91 {0x2994e043, /*L"frac34",*/ 190}, {0x2a1feb41, /*L"lambda",*/ 955},
92 {0x2ab215f3, /*L"apos",*/ 39}, {0x2ab82ef7, /*L"eacute",*/ 233},
93 {0x2b3592ef, /*L"auml",*/ 228}, {0x2ce92873, /*L"aacute",*/ 225},
94 {0x2daff48a, /*L"oslash",*/ 248}, {0x2ef68882, /*L"aelig",*/ 230},
95 {0x3061d3d3, /*L"Atilde",*/ 195}, {0x314b1b6b, /*L"Yacute",*/ 221},
96 {0x337c14e7, /*L"Uacute",*/ 218}, {0x37676aca, /*L"cent",*/ 162},
97 {0x37d0b841, /*L"circ",*/ 710}, {0x386e7947, /*L"cong",*/ 8773},
98 {0x386e839b, /*L"copy",*/ 169}, {0x3a0e225a, /*L"Epsilon",*/ 917},
99 {0x3ba7b721, /*L"Lambda",*/ 923}, {0x3bd9abe6, /*L"Alpha",*/ 913},
100 {0x3c3ffad7, /*L"Eacute",*/ 201}, {0x3cfaf69f, /*L"brvbar",*/ 166},
101 {0x3d54a489, /*L"omega",*/ 969}, {0x3e70f453, /*L"Aacute",*/ 193},
102 {0x3f37c06a, /*L"Oslash",*/ 216}, {0x40e1b34e, /*L"diams",*/ 9830},
103 {0x416596df, /*L"plusmn",*/ 177}, {0x4354ff16, /*L"Ucirc",*/ 219},
104 {0x454fce6a, /*L"Upsilon",*/ 933}, {0x4610ad35, /*L"emsp",*/ 8195},
105 {0x462afb76, /*L"ensp",*/ 8194}, {0x46e30073, /*L"euml",*/ 235},
106 {0x46e31a1b, /*L"euro",*/ 8364}, {0x46f2eada, /*L"lowast",*/ 8727},
107 {0x4dca26cf, /*L"Auml",*/ 196}, {0x4e2d6083, /*L"image",*/ 8465},
108 {0x4f964ee8, /*L"notin",*/ 8713}, {0x50917a7a, /*L"epsilon",*/ 949},
109 {0x52f9a4cd, /*L"Kappa",*/ 922}, {0x5496f410, /*L"Ocirc",*/ 212},
110 {0x568cbf34, /*L"zeta",*/ 950}, {0x57badd20, /*L"ntilde",*/ 241},
111 {0x58662109, /*L"zwnj",*/ 8204}, {0x5b39870f, /*L"empty",*/ 8709},
112 {0x5bd3268a, /*L"upsilon",*/ 965}, {0x5e2bf8a3, /*L"Gamma",*/ 915},
113 {0x5f73c13a, /*L"rsquo",*/ 8217}, {0x61f2bc4d, /*L"iota",*/ 953},
114 {0x625bbcf3, /*L"isin",*/ 8712}, {0x62906df7, /*L"iuml",*/ 239},
115 {0x64a5cb31, /*L"Aring",*/ 197}, {0x66f25c4a, /*L"sbquo",*/ 8218},
116 {0x6851ab60, /*L"spades",*/ 9824}, {0x6942a900, /*L"Ntilde",*/ 209},
117 {0x69779453, /*L"Euml",*/ 203}, {0x6cda6e23, /*L"current",*/ 164},
118 {0x70b5b634, /*L"lsquo",*/ 8216}, {0x715a3706, /*L"Ecirc",*/ 202},
119 {0x71e8bf8d, /*L"tdquo",*/ 8221}, {0x72651431, /*L"Sigma",*/ 931},
120 {0x7569813b, /*L"iquest",*/ 191}, {0x776a436a, /*L"equiv",*/ 8801},
121 {0x79215314, /*L"Zeta",*/ 918}, {0x79b81224, /*L"ograve",*/ 242},
122 {0x7c2f8b23, /*L"macr",*/ 175}, {0x7cdb8502, /*L"Acirc",*/ 194},
123 {0x8185c62e, /*L"ndash",*/ 8211}, {0x8260364a, /*L"Delta",*/ 916},
124 {0x846619ad, /*L"mdash",*/ 8212}, {0x8550fb50, /*L"OElig",*/ 338},
125 {0x88eb5b85, /*L"ldquo",*/ 8220}, {0x8b3fde04, /*L"Ograve",*/ 210},
126 {0x8bc5794b, /*L"ordf",*/ 170}, {0x8bc57952, /*L"ordm",*/ 186},
127 {0x8c14923d, /*L"ouml",*/ 246}, {0x8c5a7cd6, /*L"theta",*/ 952},
128 {0x8d61812b, /*L"thorn",*/ 254}, {0x912b95aa, /*L"asymp",*/ 8776},
129 {0x947faf81, /*L"middot",*/ 183}, {0x9629202e, /*L"lfloor",*/ 8970},
130 {0x972e9ec1, /*L"otilde",*/ 245}, {0x9748f231, /*L"otimes",*/ 8855},
131 {0x995f1469, /*L"Omega",*/ 937}, {0x99eb5349, /*L"quot",*/ 34},
132 {0x9aeb639e, /*L"hellip",*/ 8230}, {0xa0ae2f86, /*L"Scaron",*/ 352},
133 {0xa4dcb0d5, /*L"lsaquo",*/ 8249}, {0xa53dbf41, /*L"oacute",*/ 243},
134 {0xa5ae9e7b, /*L"bdquo",*/ 8222}, {0xa602d7ba, /*L"sdot",*/ 8901},
135 {0xa61ce86f, /*L"sect",*/ 167}, {0xa6e4c3d7, /*L"sigmaf",*/ 962},
136 {0xa7c1c74f, /*L"sube",*/ 8838}, {0xa7c20ee9, /*L"sup1",*/ 185},
137 {0xa7c20eea, /*L"sup2",*/ 178}, {0xa7c20eeb, /*L"sup3",*/ 179},
138 {0xa7c20f1d, /*L"supe",*/ 8839}, {0xa8b66aa1, /*L"Otilde",*/ 213},
139 {0xad958c42, /*L"AElig",*/ 198}, {0xaea9261d, /*L"Ouml",*/ 214},
140 {0xb040eafa, /*L"uArr",*/ 8657}, {0xb07c2e1c, /*L"beta",*/ 946},
141 {0xb220e92f, /*L"bull",*/ 8226}, {0xb22750c4, /*L"ccedil",*/ 231},
142 {0xb38ab31a, /*L"uarr",*/ 8593}, {0xb598b683, /*L"uuml",*/ 252},
143 {0xb6c58b21, /*L"Oacute",*/ 211}, {0xb6d2a617, /*L"oline",*/ 8254},
144 {0xba9fd989, /*L"dArr",*/ 8659}, {0xbb5ccd41, /*L"lgrave",*/ 204},
145 {0xbd39b44c, /*L"weierp",*/ 8472}, {0xbde9a1a9, /*L"darr",*/ 8595},
146 {0xc027e329, /*L"permil",*/ 8240}, {0xc2451389, /*L"upsih",*/ 978},
147 {0xc3af1ca4, /*L"Ccedil",*/ 199}, {0xcd164249, /*L"fnof",*/ 402},
148 {0xcf6c8467, /*L"hearts",*/ 9829}, {0xd1228390, /*L"trade",*/ 8482},
149 {0xd1462407, /*L"yuml",*/ 255}, {0xd2cf2253, /*L"oplus",*/ 8853},
150 {0xd310c1fc, /*L"Beta",*/ 914}, {0xd59c4d74, /*L"infin",*/ 8734},
151 {0xd64d470d, /*L"hArr",*/ 8660}, {0xd67d9c75, /*L"divide",*/ 247},
152 {0xd698dd37, /*L"Omicron",*/ 927}, {0xd82d4a63, /*L"Uuml",*/ 220},
153 {0xd9970f2d, /*L"harr",*/ 8596}, {0xda91fd99, /*L"clubs",*/ 9827},
154 {0xdbe5bdcc, /*L"there4",*/ 8756}, {0xdd7671bd, /*L"prime",*/ 8242},
155 {0xdfcf3c06, /*L"alpha",*/ 945}, {0xe0213063, /*L"saron",*/ 353},
156 {0xe1911d83, /*L"radic",*/ 8730}, {0xe2e75468, /*L"raquo",*/ 187},
157 {0xe6e27a5e, /*L"lacute",*/ 205}, {0xe74a8f36, /*L"ucirc",*/ 251},
158 {0xe864ecb6, /*L"Theta",*/ 920}, {0xecddde5e, /*L"nabla",*/ 8711},
159 {0xed1c3557, /*L"omicron",*/ 959}, {0xef82228f, /*L"rceil",*/ 8969},
160 {0xf1fab491, /*L"lArr",*/ 8656}, {0xf3dab7e7, /*L"Yuml",*/ 376},
161 {0xf4294962, /*L"laquo",*/ 171}, {0xf5446822, /*L"lang",*/ 9001},
162 {0xf5447cb1, /*L"larr",*/ 8592}, {0xf66e9bea, /*L"ugrave",*/ 249},
163 {0xf6b4ce70, /*L"lota",*/ 921}, {0xf6ef34ed, /*L"kappa",*/ 954},
164 {0xf72a3a56, /*L"thinsp",*/ 8201}, {0xf752801a, /*L"luml",*/ 207},
165 {0xf88c8430, /*L"ocirc",*/ 244}, {0xf9676178, /*L"frasl",*/ 8260},
166 {0xfd01885e, /*L"igrave",*/ 236}, {0xff3281da, /*L"egrave",*/ 232},
Dan Sinclair1770c022016-03-14 14:14:16 -0400167};
168
169const XFA_FMHtmlReserveCode reservesForEncode[] = {
170 {34, L"quot"}, {38, L"amp"}, {39, L"apos"},
171 {60, L"lt"}, {62, L"gt"}, {160, L"nbsp"},
172 {161, L"iexcl"}, {162, L"cent"}, {163, L"pund"},
173 {164, L"current"}, {165, L"yen"}, {166, L"brvbar"},
174 {167, L"sect"}, {168, L"uml"}, {169, L"copy"},
175 {170, L"ordf"}, {171, L"laquo"}, {172, L"not"},
176 {173, L"shy"}, {174, L"reg"}, {175, L"macr"},
177 {176, L"deg"}, {177, L"plusmn"}, {178, L"sup2"},
178 {179, L"sup3"}, {180, L"acute"}, {181, L"micro"},
179 {182, L"para"}, {183, L"middot"}, {184, L"cedil"},
180 {185, L"sup1"}, {186, L"ordm"}, {187, L"raquo"},
181 {188, L"frac14"}, {189, L"frac12"}, {190, L"frac34"},
182 {191, L"iquest"}, {192, L"Agrave"}, {193, L"Aacute"},
183 {194, L"Acirc"}, {195, L"Atilde"}, {196, L"Auml"},
184 {197, L"Aring"}, {198, L"AElig"}, {199, L"Ccedil"},
185 {200, L"Egrave"}, {201, L"Eacute"}, {202, L"Ecirc"},
186 {203, L"Euml"}, {204, L"lgrave"}, {205, L"lacute"},
187 {206, L"lcirc"}, {207, L"luml"}, {208, L"ETH"},
188 {209, L"Ntilde"}, {210, L"Ograve"}, {211, L"Oacute"},
189 {212, L"Ocirc"}, {213, L"Otilde"}, {214, L"Ouml"},
190 {215, L"times"}, {216, L"Oslash"}, {217, L"Ugrave"},
191 {218, L"Uacute"}, {219, L"Ucirc"}, {220, L"Uuml"},
192 {221, L"Yacute"}, {222, L"THORN"}, {223, L"szlig"},
193 {224, L"agrave"}, {225, L"aacute"}, {226, L"acirc"},
194 {227, L"atilde"}, {228, L"auml"}, {229, L"aring"},
195 {230, L"aelig"}, {231, L"ccedil"}, {232, L"egrave"},
196 {233, L"eacute"}, {234, L"ecirc"}, {235, L"euml"},
197 {236, L"igrave"}, {237, L"iacute"}, {238, L"icirc"},
198 {239, L"iuml"}, {240, L"eth"}, {241, L"ntilde"},
199 {242, L"ograve"}, {243, L"oacute"}, {244, L"ocirc"},
200 {245, L"otilde"}, {246, L"ouml"}, {247, L"divide"},
201 {248, L"oslash"}, {249, L"ugrave"}, {250, L"uacute"},
202 {251, L"ucirc"}, {252, L"uuml"}, {253, L"yacute"},
203 {254, L"thorn"}, {255, L"yuml"}, {338, L"OElig"},
204 {339, L"oelig"}, {352, L"Scaron"}, {353, L"saron"},
205 {376, L"Yuml"}, {402, L"fnof"}, {710, L"circ"},
206 {732, L"tilde"}, {913, L"Alpha"}, {914, L"Beta"},
207 {915, L"Gamma"}, {916, L"Delta"}, {917, L"Epsilon"},
208 {918, L"Zeta"}, {919, L"Eta"}, {920, L"Theta"},
209 {921, L"lota"}, {922, L"Kappa"}, {923, L"Lambda"},
210 {924, L"Mu"}, {925, L"Nu"}, {926, L"Xi"},
211 {927, L"Omicron"}, {928, L"Pi"}, {929, L"Rho"},
212 {931, L"Sigma"}, {932, L"Tau"}, {933, L"Upsilon"},
213 {934, L"Phi"}, {935, L"Chi"}, {936, L"Psi"},
214 {937, L"Omega"}, {945, L"alpha"}, {946, L"beta"},
215 {947, L"gamma"}, {948, L"delta"}, {949, L"epsilon"},
216 {950, L"zeta"}, {951, L"eta"}, {952, L"theta"},
217 {953, L"iota"}, {954, L"kappa"}, {955, L"lambda"},
218 {956, L"mu"}, {957, L"nu"}, {958, L"xi"},
219 {959, L"omicron"}, {960, L"pi"}, {961, L"rho"},
220 {962, L"sigmaf"}, {963, L"sigma"}, {964, L"tau"},
221 {965, L"upsilon"}, {966, L"phi"}, {967, L"chi"},
222 {968, L"psi"}, {969, L"omega"}, {977, L"thetasym"},
223 {978, L"upsih"}, {982, L"piv"}, {8194, L"ensp"},
224 {8195, L"emsp"}, {8201, L"thinsp"}, {8204, L"zwnj"},
225 {8205, L"zwj"}, {8206, L"lrm"}, {8207, L"rlm"},
226 {8211, L"ndash"}, {8212, L"mdash"}, {8216, L"lsquo"},
227 {8217, L"rsquo"}, {8218, L"sbquo"}, {8220, L"ldquo"},
228 {8221, L"tdquo"}, {8222, L"bdquo"}, {8224, L"dagger"},
229 {8225, L"Dagger"}, {8226, L"bull"}, {8230, L"hellip"},
230 {8240, L"permil"}, {8242, L"prime"}, {8249, L"lsaquo"},
231 {8250, L"rsaquo"}, {8254, L"oline"}, {8260, L"frasl"},
232 {8364, L"euro"}, {8465, L"image"}, {8472, L"weierp"},
233 {8476, L"real"}, {8482, L"trade"}, {8501, L"alefsym"},
234 {8592, L"larr"}, {8593, L"uarr"}, {8594, L"rarr"},
235 {8595, L"darr"}, {8596, L"harr"}, {8629, L"crarr"},
236 {8656, L"lArr"}, {8657, L"uArr"}, {8658, L"rArr"},
237 {8659, L"dArr"}, {8660, L"hArr"}, {8704, L"forall"},
238 {8706, L"part"}, {8707, L"exist"}, {8709, L"empty"},
239 {8711, L"nabla"}, {8712, L"isin"}, {8713, L"notin"},
240 {8715, L"ni"}, {8719, L"prod"}, {8721, L"sum"},
241 {8722, L"minus"}, {8727, L"lowast"}, {8730, L"radic"},
242 {8733, L"prop"}, {8734, L"infin"}, {8736, L"ang"},
243 {8743, L"and"}, {8744, L"or"}, {8745, L"cap"},
244 {8746, L"cup"}, {8747, L"int"}, {8756, L"there4"},
245 {8764, L"sim"}, {8773, L"cong"}, {8776, L"asymp"},
246 {8800, L"ne"}, {8801, L"equiv"}, {8804, L"le"},
247 {8805, L"ge"}, {8834, L"sub"}, {8835, L"sup"},
248 {8836, L"nsub"}, {8838, L"sube"}, {8839, L"supe"},
249 {8853, L"oplus"}, {8855, L"otimes"}, {8869, L"perp"},
250 {8901, L"sdot"}, {8968, L"lceil"}, {8969, L"rceil"},
251 {8970, L"lfloor"}, {8971, L"rfloor"}, {9001, L"lang"},
252 {9002, L"rang"}, {9674, L"loz"}, {9824, L"spades"},
253 {9827, L"clubs"}, {9829, L"hearts"}, {9830, L"diams"},
254};
255
tsepez1c9cfe12016-05-26 13:30:56 -0700256const FXJSE_FUNCTION_DESCRIPTOR formcalc_fm2js_functions[] = {
257 {"Abs", CXFA_FM2JSContext::Abs},
258 {"Avg", CXFA_FM2JSContext::Avg},
259 {"Ceil", CXFA_FM2JSContext::Ceil},
260 {"Count", CXFA_FM2JSContext::Count},
261 {"Floor", CXFA_FM2JSContext::Floor},
262 {"Max", CXFA_FM2JSContext::Max},
263 {"Min", CXFA_FM2JSContext::Min},
264 {"Mod", CXFA_FM2JSContext::Mod},
265 {"Round", CXFA_FM2JSContext::Round},
266 {"Sum", CXFA_FM2JSContext::Sum},
267 {"Date", CXFA_FM2JSContext::Date},
268 {"Date2Num", CXFA_FM2JSContext::Date2Num},
269 {"DateFmt", CXFA_FM2JSContext::DateFmt},
270 {"IsoDate2Num", CXFA_FM2JSContext::IsoDate2Num},
271 {"IsoTime2Num", CXFA_FM2JSContext::IsoTime2Num},
272 {"LocalDateFmt", CXFA_FM2JSContext::LocalDateFmt},
273 {"LocalTimeFmt", CXFA_FM2JSContext::LocalTimeFmt},
274 {"Num2Date", CXFA_FM2JSContext::Num2Date},
275 {"Num2GMTime", CXFA_FM2JSContext::Num2GMTime},
276 {"Num2Time", CXFA_FM2JSContext::Num2Time},
277 {"Time", CXFA_FM2JSContext::Time},
278 {"Time2Num", CXFA_FM2JSContext::Time2Num},
279 {"TimeFmt", CXFA_FM2JSContext::TimeFmt},
280 {"Apr", CXFA_FM2JSContext::Apr},
281 {"Cterm", CXFA_FM2JSContext::CTerm},
282 {"FV", CXFA_FM2JSContext::FV},
283 {"Ipmt", CXFA_FM2JSContext::IPmt},
284 {"NPV", CXFA_FM2JSContext::NPV},
285 {"Pmt", CXFA_FM2JSContext::Pmt},
286 {"PPmt", CXFA_FM2JSContext::PPmt},
287 {"PV", CXFA_FM2JSContext::PV},
288 {"Rate", CXFA_FM2JSContext::Rate},
289 {"Term", CXFA_FM2JSContext::Term},
290 {"Choose", CXFA_FM2JSContext::Choose},
291 {"Exists", CXFA_FM2JSContext::Exists},
292 {"HasValue", CXFA_FM2JSContext::HasValue},
293 {"Oneof", CXFA_FM2JSContext::Oneof},
294 {"Within", CXFA_FM2JSContext::Within},
295 {"If", CXFA_FM2JSContext::If},
296 {"Eval", CXFA_FM2JSContext::Eval},
297 {"Translate", CXFA_FM2JSContext::eval_translation},
298 {"Ref", CXFA_FM2JSContext::Ref},
299 {"UnitType", CXFA_FM2JSContext::UnitType},
300 {"UnitValue", CXFA_FM2JSContext::UnitValue},
301 {"At", CXFA_FM2JSContext::At},
302 {"Concat", CXFA_FM2JSContext::Concat},
303 {"Decode", CXFA_FM2JSContext::Decode},
304 {"Encode", CXFA_FM2JSContext::Encode},
305 {"Format", CXFA_FM2JSContext::Format},
306 {"Left", CXFA_FM2JSContext::Left},
307 {"Len", CXFA_FM2JSContext::Len},
308 {"Lower", CXFA_FM2JSContext::Lower},
309 {"Ltrim", CXFA_FM2JSContext::Ltrim},
310 {"Parse", CXFA_FM2JSContext::Parse},
311 {"Replace", CXFA_FM2JSContext::Replace},
312 {"Right", CXFA_FM2JSContext::Right},
313 {"Rtrim", CXFA_FM2JSContext::Rtrim},
314 {"Space", CXFA_FM2JSContext::Space},
315 {"Str", CXFA_FM2JSContext::Str},
316 {"Stuff", CXFA_FM2JSContext::Stuff},
317 {"Substr", CXFA_FM2JSContext::Substr},
318 {"Uuid", CXFA_FM2JSContext::Uuid},
319 {"Upper", CXFA_FM2JSContext::Upper},
320 {"WordNum", CXFA_FM2JSContext::WordNum},
321 {"Get", CXFA_FM2JSContext::Get},
322 {"Post", CXFA_FM2JSContext::Post},
323 {"Put", CXFA_FM2JSContext::Put},
324 {"positive_operator", CXFA_FM2JSContext::positive_operator},
325 {"negative_operator", CXFA_FM2JSContext::negative_operator},
326 {"logical_or_operator", CXFA_FM2JSContext::logical_or_operator},
327 {"logical_and_operator", CXFA_FM2JSContext::logical_and_operator},
328 {"logical_not_operator", CXFA_FM2JSContext::logical_not_operator},
329 {"equality_operator", CXFA_FM2JSContext::equality_operator},
330 {"notequality_operator", CXFA_FM2JSContext::notequality_operator},
331 {"less_operator", CXFA_FM2JSContext::less_operator},
332 {"lessequal_operator", CXFA_FM2JSContext::lessequal_operator},
333 {"greater_operator", CXFA_FM2JSContext::greater_operator},
334 {"greaterequal_operator", CXFA_FM2JSContext::greaterequal_operator},
335 {"plus_operator", CXFA_FM2JSContext::plus_operator},
336 {"minus_operator", CXFA_FM2JSContext::minus_operator},
337 {"multiple_operator", CXFA_FM2JSContext::multiple_operator},
338 {"divide_operator", CXFA_FM2JSContext::divide_operator},
339 {"assign_value_operator", CXFA_FM2JSContext::assign_value_operator},
340 {"dot_accessor", CXFA_FM2JSContext::dot_accessor},
341 {"dotdot_accessor", CXFA_FM2JSContext::dotdot_accessor},
342 {"concat_fm_object", CXFA_FM2JSContext::concat_fm_object},
343 {"is_fm_object", CXFA_FM2JSContext::is_fm_object},
344 {"is_fm_array", CXFA_FM2JSContext::is_fm_array},
345 {"get_fm_value", CXFA_FM2JSContext::get_fm_value},
346 {"get_fm_jsobj", CXFA_FM2JSContext::get_fm_jsobj},
347 {"fm_var_filter", CXFA_FM2JSContext::fm_var_filter},
348};
349
350const FXJSE_CLASS_DESCRIPTOR formcalc_fm2js_descriptor = {
351 "XFA_FM2JS_FormCalcClass", // name
352 nullptr, // constructor
353 nullptr, // properties
354 formcalc_fm2js_functions, // methods
355 0, // number of properties
356 FX_ArraySize(formcalc_fm2js_functions), // number of methods
357 nullptr, // dynamic prop type
358 nullptr, // dynamic prop getter
359 nullptr, // dynamic prop setter
360 nullptr, // dynamic prop deleter
361 nullptr, // dynamic prop method call
362};
363
dsinclair0c268e92016-05-17 14:04:14 -0700364const uint8_t g_sAltTable_Date[] = {
ochangf6be1452016-06-01 12:20:03 -0700365 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255,
366 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255,
367 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255,
dsinclair0c268e92016-05-17 14:04:14 -0700368};
ochangf6be1452016-06-01 12:20:03 -0700369static_assert(FX_ArraySize(g_sAltTable_Date) == L'a' - L'A' + 1,
370 "Invalid g_sAltTable_Date size.");
dsinclair0c268e92016-05-17 14:04:14 -0700371
372const uint8_t g_sAltTable_Time[] = {
ochangf6be1452016-06-01 12:20:03 -0700373 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255,
374 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255,
375 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255,
dsinclair0c268e92016-05-17 14:04:14 -0700376};
ochangf6be1452016-06-01 12:20:03 -0700377static_assert(FX_ArraySize(g_sAltTable_Time) == L'a' - L'A' + 1,
378 "Invalid g_sAltTable_Time size.");
dsinclair0c268e92016-05-17 14:04:14 -0700379
380void AlternateDateTimeSymbols(CFX_WideString& wsPattern,
381 const CFX_WideString& wsAltSymbols,
382 const uint8_t* pAltTable) {
383 int32_t nLength = wsPattern.GetLength();
tsepezd19e9122016-11-02 15:43:18 -0700384 bool bInConstRange = false;
385 bool bEscape = false;
ochangf6be1452016-06-01 12:20:03 -0700386 int32_t i = 0;
dsinclair0c268e92016-05-17 14:04:14 -0700387 while (i < nLength) {
388 FX_WCHAR wc = wsPattern[i];
389 if (wc == L'\'') {
390 bInConstRange = !bInConstRange;
391 if (bEscape) {
392 i++;
393 } else {
394 wsPattern.Delete(i);
395 nLength--;
396 }
397 bEscape = !bEscape;
398 continue;
399 }
ochangf6be1452016-06-01 12:20:03 -0700400 if (!bInConstRange && wc >= L'A' && wc <= L'a') {
401 uint8_t nAlt = pAltTable[wc - L'A'];
dsinclair48d91dd2016-05-31 11:54:01 -0700402 if (nAlt != 255)
dsinclair0c268e92016-05-17 14:04:14 -0700403 wsPattern.SetAt(i, wsAltSymbols[nAlt]);
dsinclair0c268e92016-05-17 14:04:14 -0700404 }
405 i++;
tsepezd19e9122016-11-02 15:43:18 -0700406 bEscape = false;
dsinclair0c268e92016-05-17 14:04:14 -0700407 }
408}
409
dsinclair48d91dd2016-05-31 11:54:01 -0700410bool PatternStringType(const CFX_ByteStringC& szPattern,
411 uint32_t& patternType) {
412 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern);
413 if (FX_WSTRC(L"datetime") == wsPattern.Left(8)) {
414 patternType = XFA_VT_DATETIME;
415 return true;
416 }
417 if (FX_WSTRC(L"date") == wsPattern.Left(4)) {
418 patternType = wsPattern.Find(L"time") > 0 ? XFA_VT_DATETIME : XFA_VT_DATE;
419 return true;
420 }
421 if (FX_WSTRC(L"time") == wsPattern.Left(4)) {
422 patternType = XFA_VT_TIME;
423 return true;
424 }
425 if (FX_WSTRC(L"text") == wsPattern.Left(4)) {
426 patternType = XFA_VT_TEXT;
427 return true;
428 }
429 if (FX_WSTRC(L"num") == wsPattern.Left(3)) {
430 if (FX_WSTRC(L"integer") == wsPattern.Mid(4, 7)) {
431 patternType = XFA_VT_INTEGER;
432 } else if (FX_WSTRC(L"decimal") == wsPattern.Mid(4, 7)) {
433 patternType = XFA_VT_DECIMAL;
434 } else if (FX_WSTRC(L"currency") == wsPattern.Mid(4, 8)) {
435 patternType = XFA_VT_FLOAT;
436 } else if (FX_WSTRC(L"percent") == wsPattern.Mid(4, 7)) {
437 patternType = XFA_VT_FLOAT;
438 } else {
439 patternType = XFA_VT_FLOAT;
440 }
441 return true;
442 }
443
444 patternType = XFA_VT_NULL;
445 wsPattern.MakeLower();
446 const FX_WCHAR* pData = wsPattern.c_str();
447 int32_t iLength = wsPattern.GetLength();
448 int32_t iIndex = 0;
tsepezd19e9122016-11-02 15:43:18 -0700449 bool bSingleQuotation = false;
dsinclair48d91dd2016-05-31 11:54:01 -0700450 FX_WCHAR patternChar;
451 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -0700452 patternChar = pData[iIndex];
dsinclair48d91dd2016-05-31 11:54:01 -0700453 if (patternChar == 0x27) {
454 bSingleQuotation = !bSingleQuotation;
455 } else if (!bSingleQuotation &&
456 (patternChar == 'y' || patternChar == 'j')) {
457 patternType = XFA_VT_DATE;
458 iIndex++;
459 FX_WCHAR timePatternChar;
460 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -0700461 timePatternChar = pData[iIndex];
dsinclair48d91dd2016-05-31 11:54:01 -0700462 if (timePatternChar == 0x27) {
463 bSingleQuotation = !bSingleQuotation;
464 } else if (!bSingleQuotation && timePatternChar == 't') {
465 patternType = XFA_VT_DATETIME;
466 break;
467 }
468 iIndex++;
469 }
470 break;
471 } else if (!bSingleQuotation &&
472 (patternChar == 'h' || patternChar == 'k')) {
473 patternType = XFA_VT_TIME;
474 break;
475 } else if (!bSingleQuotation &&
476 (patternChar == 'a' || patternChar == 'x' ||
477 patternChar == 'o' || patternChar == '0')) {
478 patternType = XFA_VT_TEXT;
479 if (patternChar == 'x' || patternChar == 'o' || patternChar == '0') {
480 break;
481 }
482 } else if (!bSingleQuotation &&
483 (patternChar == 'z' || patternChar == 's' ||
484 patternChar == 'e' || patternChar == 'v' ||
485 patternChar == '8' || patternChar == ',' ||
486 patternChar == '.' || patternChar == '$')) {
487 patternType = XFA_VT_FLOAT;
488 if (patternChar == 'v' || patternChar == '8' || patternChar == '$') {
489 break;
490 }
491 }
492 iIndex++;
493 }
494 if (patternType == XFA_VT_NULL) {
495 patternType = XFA_VT_TEXT | XFA_VT_FLOAT;
496 }
497 return false;
498}
499
dsinclair8f3074b2016-06-02 17:45:25 -0700500CXFA_FM2JSContext* ToJSContext(CFXJSE_Value* pValue, CFXJSE_Class* pClass) {
501 return static_cast<CXFA_FM2JSContext*>(pValue->ToHostObject(pClass));
502}
503
dsinclair2b6d64e2016-06-06 11:39:42 -0700504bool IsWhitespace(char c) {
505 return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A ||
506 c == 0x0D;
507}
508
Dan Sinclair1770c022016-03-14 14:14:16 -0400509} // namespace
510
dsinclair48d91dd2016-05-31 11:54:01 -0700511// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700512void CXFA_FM2JSContext::Abs(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400513 const CFX_ByteStringC& szFuncName,
514 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700515 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700516 ToJSContext(pThis, nullptr)
517 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Abs");
dsinclair89ba6de2016-05-31 12:11:22 -0700518 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400519 }
dsinclair89ba6de2016-05-31 12:11:22 -0700520
521 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
522 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700523 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700524 return;
525 }
526
527 FX_DOUBLE dValue = ValueToDouble(pThis, argOne.get());
528 if (dValue < 0)
529 dValue = -dValue;
530
dsinclairf27aeec2016-06-07 19:36:18 -0700531 args.GetReturnValue()->SetDouble(dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400532}
dsinclair48d91dd2016-05-31 11:54:01 -0700533
534// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700535void CXFA_FM2JSContext::Avg(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400536 const CFX_ByteStringC& szFuncName,
537 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700538 int32_t argc = args.GetLength();
539 if (argc < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -0700540 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700541 return;
542 }
543
dsinclair8f3074b2016-06-02 17:45:25 -0700544 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400545 uint32_t uCount = 0;
546 FX_DOUBLE dSum = 0.0;
dsinclair89ba6de2016-05-31 12:11:22 -0700547 for (int32_t i = 0; i < argc; i++) {
548 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700549 if (argValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700550 continue;
dsinclair86fad992016-05-31 11:34:04 -0700551
dsinclair769b1372016-06-08 13:12:41 -0700552 if (!argValue->IsArray()) {
dsinclair89ba6de2016-05-31 12:11:22 -0700553 dSum += ValueToDouble(pThis, argValue.get());
554 uCount++;
555 continue;
556 }
557
558 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700559 argValue->GetObjectProperty("length", lengthValue.get());
560 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700561
562 if (iLength > 2) {
563 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700564 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700565
566 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
dsinclair769b1372016-06-08 13:12:41 -0700567 if (propertyValue->IsNull()) {
dsinclair89ba6de2016-05-31 12:11:22 -0700568 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700569 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700570 std::unique_ptr<CFXJSE_Value> defaultPropValue(
dsinclair86fad992016-05-31 11:34:04 -0700571 new CFXJSE_Value(pIsolate));
dsinclair89ba6de2016-05-31 12:11:22 -0700572 GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700573 if (defaultPropValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700574 continue;
575
576 dSum += ValueToDouble(pThis, defaultPropValue.get());
577 uCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400578 }
579 } else {
dsinclair89ba6de2016-05-31 12:11:22 -0700580 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700581 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700582 std::unique_ptr<CFXJSE_Value> newPropertyValue(
583 new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -0700584 jsObjectValue->GetObjectProperty(
585 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700586 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700587 continue;
588
589 dSum += ValueToDouble(pThis, newPropertyValue.get());
590 uCount++;
591 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400592 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400593 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400594 }
dsinclair89ba6de2016-05-31 12:11:22 -0700595 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700596 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700597 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400598 }
dsinclair89ba6de2016-05-31 12:11:22 -0700599
dsinclairf27aeec2016-06-07 19:36:18 -0700600 args.GetReturnValue()->SetDouble(dSum / uCount);
Dan Sinclair1770c022016-03-14 14:14:16 -0400601}
dsinclair48d91dd2016-05-31 11:54:01 -0700602
603// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700604void CXFA_FM2JSContext::Ceil(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400605 const CFX_ByteStringC& szFuncName,
606 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700607 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700608 ToJSContext(pThis, nullptr)
609 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ceil");
dsinclair89ba6de2016-05-31 12:11:22 -0700610 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400611 }
dsinclair89ba6de2016-05-31 12:11:22 -0700612
613 std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0);
614 if (ValueIsNull(pThis, argValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700615 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700616 return;
617 }
618
dsinclairf27aeec2016-06-07 19:36:18 -0700619 args.GetReturnValue()->SetFloat(
620 FXSYS_ceil(ValueToFloat(pThis, argValue.get())));
Dan Sinclair1770c022016-03-14 14:14:16 -0400621}
dsinclair48d91dd2016-05-31 11:54:01 -0700622
623// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700624void CXFA_FM2JSContext::Count(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400625 const CFX_ByteStringC& szFuncName,
626 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700627 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700628 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
dsinclair89ba6de2016-05-31 12:11:22 -0700629 int32_t iCount = 0;
dsinclair48d91dd2016-05-31 11:54:01 -0700630 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700631 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700632 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400633 continue;
dsinclair89ba6de2016-05-31 12:11:22 -0700634
dsinclair769b1372016-06-08 13:12:41 -0700635 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700636 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700637 argValue->GetObjectProperty("length", lengthValue.get());
dsinclair86fad992016-05-31 11:34:04 -0700638
dsinclairf27aeec2016-06-07 19:36:18 -0700639 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700640 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700641 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclair89ba6de2016-05-31 12:11:22 -0700642 return;
643 }
644
645 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
646 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
647 std::unique_ptr<CFXJSE_Value> newPropertyValue(
648 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700649 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
650 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700651 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700652 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700653 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700654 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700655 if (!newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700656 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400657 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400658 } else {
weilidb444d22016-06-02 15:48:15 -0700659 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700660 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700661 jsObjectValue->GetObjectProperty(
662 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700663 iCount += newPropertyValue->IsNull() ? 0 : 1;
dsinclair89ba6de2016-05-31 12:11:22 -0700664 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400665 }
dsinclair769b1372016-06-08 13:12:41 -0700666 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700667 std::unique_ptr<CFXJSE_Value> newPropertyValue(
668 new CFXJSE_Value(pIsolate));
669 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700670 if (!newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700671 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400672 } else {
dsinclair89ba6de2016-05-31 12:11:22 -0700673 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400674 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400675 }
dsinclairf27aeec2016-06-07 19:36:18 -0700676 args.GetReturnValue()->SetInteger(iCount);
Dan Sinclair1770c022016-03-14 14:14:16 -0400677}
dsinclair48d91dd2016-05-31 11:54:01 -0700678
679// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700680void CXFA_FM2JSContext::Floor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400681 const CFX_ByteStringC& szFuncName,
682 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700683 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700684 ToJSContext(pThis, nullptr)
685 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Floor");
dsinclair89ba6de2016-05-31 12:11:22 -0700686 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400687 }
dsinclair89ba6de2016-05-31 12:11:22 -0700688
689 std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0);
690 if (ValueIsNull(pThis, argValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700691 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700692 return;
693 }
694
dsinclairf27aeec2016-06-07 19:36:18 -0700695 args.GetReturnValue()->SetFloat(
696 FXSYS_floor(ValueToFloat(pThis, argValue.get())));
Dan Sinclair1770c022016-03-14 14:14:16 -0400697}
dsinclair48d91dd2016-05-31 11:54:01 -0700698
699// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700700void CXFA_FM2JSContext::Max(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400701 const CFX_ByteStringC& szFuncName,
702 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700703 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700704 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400705 uint32_t uCount = 0;
706 FX_DOUBLE dMaxValue = 0.0;
dsinclair48d91dd2016-05-31 11:54:01 -0700707 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700708 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700709 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400710 continue;
dsinclair89ba6de2016-05-31 12:11:22 -0700711
dsinclair769b1372016-06-08 13:12:41 -0700712 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700713 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700714 argValue->GetObjectProperty("length", lengthValue.get());
715 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700716 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700717 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclair89ba6de2016-05-31 12:11:22 -0700718 return;
719 }
dsinclair86fad992016-05-31 11:34:04 -0700720
dsinclair89ba6de2016-05-31 12:11:22 -0700721 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
722 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
723 std::unique_ptr<CFXJSE_Value> newPropertyValue(
724 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700725 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
726 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700727 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700728 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700729 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700730 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700731 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700732 continue;
733
734 uCount++;
735 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
736 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400737 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400738 } else {
weilidb444d22016-06-02 15:48:15 -0700739 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700740 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700741 jsObjectValue->GetObjectProperty(
742 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700743 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700744 continue;
745
746 uCount++;
747 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
748 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
749 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400750 }
dsinclair769b1372016-06-08 13:12:41 -0700751 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700752 std::unique_ptr<CFXJSE_Value> newPropertyValue(
753 new CFXJSE_Value(pIsolate));
754 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700755 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700756 continue;
757
758 uCount++;
759 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
760 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400761 } else {
762 uCount++;
dsinclair89ba6de2016-05-31 12:11:22 -0700763 FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get());
764 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400765 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400766 }
dsinclair89ba6de2016-05-31 12:11:22 -0700767 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700768 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700769 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400770 }
dsinclair89ba6de2016-05-31 12:11:22 -0700771
dsinclairf27aeec2016-06-07 19:36:18 -0700772 args.GetReturnValue()->SetDouble(dMaxValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400773}
dsinclair48d91dd2016-05-31 11:54:01 -0700774
775// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700776void CXFA_FM2JSContext::Min(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400777 const CFX_ByteStringC& szFuncName,
778 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700779 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700780 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400781 uint32_t uCount = 0;
782 FX_DOUBLE dMinValue = 0.0;
dsinclair48d91dd2016-05-31 11:54:01 -0700783 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700784 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700785 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400786 continue;
dsinclairdbdcb812016-06-01 20:07:22 -0700787
dsinclair769b1372016-06-08 13:12:41 -0700788 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700789 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700790 argValue->GetObjectProperty("length", lengthValue.get());
791 int32_t iLength = lengthValue->ToInteger();
dsinclairdbdcb812016-06-01 20:07:22 -0700792 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700793 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700794 return;
795 }
796
797 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
798 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
799 std::unique_ptr<CFXJSE_Value> newPropertyValue(
800 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700801 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
802 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700803 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700804 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700805 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700806 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700807 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700808 continue;
809
810 uCount++;
811 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
812 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400813 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400814 } else {
weilidb444d22016-06-02 15:48:15 -0700815 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700816 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700817 jsObjectValue->GetObjectProperty(
818 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700819 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700820 continue;
821
822 uCount++;
823 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
824 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
825 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400826 }
dsinclair769b1372016-06-08 13:12:41 -0700827 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700828 std::unique_ptr<CFXJSE_Value> newPropertyValue(
829 new CFXJSE_Value(pIsolate));
830 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700831 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700832 continue;
833
834 uCount++;
835 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
836 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400837 } else {
838 uCount++;
dsinclairdbdcb812016-06-01 20:07:22 -0700839 FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get());
840 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400841 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400842 }
dsinclairdbdcb812016-06-01 20:07:22 -0700843 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700844 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700845 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400846 }
dsinclairdbdcb812016-06-01 20:07:22 -0700847
dsinclairf27aeec2016-06-07 19:36:18 -0700848 args.GetReturnValue()->SetDouble(dMinValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400849}
dsinclair48d91dd2016-05-31 11:54:01 -0700850
851// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700852void CXFA_FM2JSContext::Mod(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400853 const CFX_ByteStringC& szFuncName,
854 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700855 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairdbdcb812016-06-01 20:07:22 -0700856 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700857 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Mod");
dsinclairdbdcb812016-06-01 20:07:22 -0700858 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400859 }
dsinclairdbdcb812016-06-01 20:07:22 -0700860
861 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
862 std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1);
dsinclair769b1372016-06-08 13:12:41 -0700863 if (argOne->IsNull() || argTwo->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700864 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700865 return;
866 }
867
868 bool argOneResult;
869 FX_DOUBLE dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult);
870 bool argTwoResult;
871 FX_DOUBLE dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult);
872 if (!argOneResult || !argTwoResult) {
dsinclair2235b7b2016-06-02 07:42:25 -0700873 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700874 return;
875 }
876
877 if (dDivisor == 0.0) {
dsinclair2235b7b2016-06-02 07:42:25 -0700878 pContext->ThrowException(XFA_IDS_DIVIDE_ZERO);
dsinclairdbdcb812016-06-01 20:07:22 -0700879 return;
880 }
881
dsinclairf27aeec2016-06-07 19:36:18 -0700882 args.GetReturnValue()->SetDouble(dDividend -
883 dDivisor * (int32_t)(dDividend / dDivisor));
Dan Sinclair1770c022016-03-14 14:14:16 -0400884}
dsinclair48d91dd2016-05-31 11:54:01 -0700885
886// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700887void CXFA_FM2JSContext::Round(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400888 const CFX_ByteStringC& szFuncName,
889 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700890 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400891 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -0700892 if (argc < 1 || argc > 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700893 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Round");
dsinclairdbdcb812016-06-01 20:07:22 -0700894 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400895 }
dsinclairdbdcb812016-06-01 20:07:22 -0700896
897 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
dsinclair769b1372016-06-08 13:12:41 -0700898 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700899 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700900 return;
901 }
902
903 bool dValueRet;
904 FX_DOUBLE dValue = ExtractDouble(pThis, argOne.get(), &dValueRet);
905 if (!dValueRet) {
dsinclair2235b7b2016-06-02 07:42:25 -0700906 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700907 return;
908 }
909
910 uint8_t uPrecision = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -0700911 if (argc > 1) {
dsinclairdbdcb812016-06-01 20:07:22 -0700912 std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1);
dsinclair769b1372016-06-08 13:12:41 -0700913 if (argTwo->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700914 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700915 return;
916 }
917
918 bool dPrecisionRet;
919 FX_DOUBLE dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet);
920 if (!dPrecisionRet) {
dsinclair2235b7b2016-06-02 07:42:25 -0700921 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700922 return;
923 }
924
925 uPrecision =
926 static_cast<uint8_t>(std::min(std::max(dPrecision, 0.0), 12.0));
927 }
928
929 CFX_Decimal decimalValue((FX_FLOAT)dValue, uPrecision);
930 CFX_WideString wsValue = decimalValue;
dsinclairf27aeec2016-06-07 19:36:18 -0700931 args.GetReturnValue()->SetString(wsValue.UTF8Encode().AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -0400932}
dsinclair48d91dd2016-05-31 11:54:01 -0700933
934// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700935void CXFA_FM2JSContext::Sum(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400936 const CFX_ByteStringC& szFuncName,
937 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -0700938 int32_t argc = args.GetLength();
939 if (argc == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700940 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700941 return;
942 }
943
dsinclair8f3074b2016-06-02 17:45:25 -0700944 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700945 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400946 uint32_t uCount = 0;
947 FX_DOUBLE dSum = 0.0;
dsinclairdbdcb812016-06-01 20:07:22 -0700948 for (int32_t i = 0; i < argc; i++) {
949 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700950 if (argValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700951 continue;
952
dsinclair769b1372016-06-08 13:12:41 -0700953 if (argValue->IsArray()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700954 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700955 argValue->GetObjectProperty("length", lengthValue.get());
956 int32_t iLength = lengthValue->ToInteger();
dsinclairdbdcb812016-06-01 20:07:22 -0700957 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700958 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700959 return;
960 }
961
962 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700963 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700964 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
965 std::unique_ptr<CFXJSE_Value> newPropertyValue(
966 new CFXJSE_Value(pIsolate));
dsinclair769b1372016-06-08 13:12:41 -0700967 if (propertyValue->IsNull()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700968 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700969 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700970 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700971 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700972 continue;
973
974 dSum += ValueToDouble(pThis, jsObjectValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -0400975 uCount++;
976 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400977 } else {
dsinclairdbdcb812016-06-01 20:07:22 -0700978 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700979 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700980 jsObjectValue->GetObjectProperty(
981 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700982 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700983 continue;
984
985 dSum += ValueToDouble(pThis, newPropertyValue.get());
986 uCount++;
987 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400988 }
dsinclair769b1372016-06-08 13:12:41 -0700989 } else if (argValue->IsObject()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700990 std::unique_ptr<CFXJSE_Value> newPropertyValue(
991 new CFXJSE_Value(pIsolate));
992 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700993 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700994 continue;
995
996 dSum += ValueToDouble(pThis, argValue.get());
997 uCount++;
998 } else {
999 dSum += ValueToDouble(pThis, argValue.get());
1000 uCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -04001001 }
Dan Sinclair1770c022016-03-14 14:14:16 -04001002 }
dsinclairdbdcb812016-06-01 20:07:22 -07001003 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001004 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001005 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001006 }
dsinclairdbdcb812016-06-01 20:07:22 -07001007
dsinclairf27aeec2016-06-07 19:36:18 -07001008 args.GetReturnValue()->SetDouble(dSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04001009}
dsinclair48d91dd2016-05-31 11:54:01 -07001010
1011// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001012void CXFA_FM2JSContext::Date(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001013 const CFX_ByteStringC& szFuncName,
1014 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -07001015 if (args.GetLength() != 0) {
dsinclair8f3074b2016-06-02 17:45:25 -07001016 ToJSContext(pThis, nullptr)
1017 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date");
dsinclairdbdcb812016-06-01 20:07:22 -07001018 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001019 }
dsinclairdbdcb812016-06-01 20:07:22 -07001020
1021 time_t currentTime;
1022 time(&currentTime);
1023 struct tm* pTmStruct = gmtime(&currentTime);
1024
1025 CFX_ByteString bufferYear;
1026 CFX_ByteString bufferMon;
1027 CFX_ByteString bufferDay;
1028 bufferYear.Format("%d", pTmStruct->tm_year + 1900);
1029 bufferMon.Format("%02d", pTmStruct->tm_mon + 1);
1030 bufferDay.Format("%02d", pTmStruct->tm_mday);
1031
1032 CFX_ByteString bufferCurrent = bufferYear + bufferMon + bufferDay;
dsinclairf27aeec2016-06-07 19:36:18 -07001033 args.GetReturnValue()->SetInteger(DateString2Num(bufferCurrent.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001034}
dsinclair48d91dd2016-05-31 11:54:01 -07001035
1036// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001037void CXFA_FM2JSContext::Date2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001038 const CFX_ByteStringC& szFuncName,
1039 CFXJSE_Arguments& args) {
1040 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001041 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001042 ToJSContext(pThis, nullptr)
1043 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001044 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001045 }
dsinclairdbdcb812016-06-01 20:07:22 -07001046
1047 std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0);
1048 if (ValueIsNull(pThis, dateValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001049 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001050 return;
1051 }
1052
1053 CFX_ByteString dateString;
1054 ValueToUTF8String(dateValue.get(), dateString);
1055
1056 CFX_ByteString formatString;
1057 if (argc > 1) {
1058 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1059 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001060 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001061 return;
1062 }
1063 ValueToUTF8String(formatValue.get(), formatString);
1064 }
1065
1066 CFX_ByteString localString;
dsinclair2b6d64e2016-06-06 11:39:42 -07001067 if (argc > 2) {
dsinclairdbdcb812016-06-01 20:07:22 -07001068 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1069 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001070 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001071 return;
1072 }
1073 ValueToUTF8String(localValue.get(), localString);
1074 }
1075
1076 CFX_ByteString szIsoDateString;
1077 if (!Local2IsoDate(pThis, dateString.AsStringC(), formatString.AsStringC(),
1078 localString.AsStringC(), szIsoDateString)) {
dsinclairf27aeec2016-06-07 19:36:18 -07001079 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001080 return;
1081 }
1082
dsinclairf27aeec2016-06-07 19:36:18 -07001083 args.GetReturnValue()->SetInteger(
1084 DateString2Num(szIsoDateString.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001085}
dsinclair48d91dd2016-05-31 11:54:01 -07001086
1087// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001088void CXFA_FM2JSContext::DateFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001089 const CFX_ByteStringC& szFuncName,
1090 CFXJSE_Arguments& args) {
1091 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001092 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001093 ToJSContext(pThis, nullptr)
1094 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001095 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001096 }
dsinclairdbdcb812016-06-01 20:07:22 -07001097
1098 int32_t iStyle = 0;
1099 if (argc > 0) {
1100 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001101 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001102 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001103 return;
1104 }
1105
1106 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1107 if (iStyle < 0 || iStyle > 4)
1108 iStyle = 0;
1109 }
1110
1111 CFX_ByteString szLocal;
dsinclair2b6d64e2016-06-06 11:39:42 -07001112 if (argc > 1) {
dsinclairdbdcb812016-06-01 20:07:22 -07001113 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001114 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001115 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001116 return;
1117 }
1118 ValueToUTF8String(argLocal.get(), szLocal);
1119 }
1120
1121 CFX_ByteString formatStr;
1122 GetStandardDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr);
dsinclairf27aeec2016-06-07 19:36:18 -07001123 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001124}
dsinclair48d91dd2016-05-31 11:54:01 -07001125
1126// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001127void CXFA_FM2JSContext::IsoDate2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001128 const CFX_ByteStringC& szFuncName,
1129 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -07001130 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07001131 ToJSContext(pThis, nullptr)
1132 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"IsoDate2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001133 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001134 }
dsinclairdbdcb812016-06-01 20:07:22 -07001135
1136 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001137 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001138 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001139 return;
1140 }
1141
1142 CFX_ByteString szArgString;
1143 ValueToUTF8String(argOne.get(), szArgString);
dsinclairf27aeec2016-06-07 19:36:18 -07001144 args.GetReturnValue()->SetInteger(DateString2Num(szArgString.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001145}
dsinclair48d91dd2016-05-31 11:54:01 -07001146
1147// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001148void CXFA_FM2JSContext::IsoTime2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001149 const CFX_ByteStringC& szFuncName,
1150 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07001151 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairdbdcb812016-06-01 20:07:22 -07001152 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07001153 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD,
1154 L"IsoTime2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001155 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001156 }
dsinclairdbdcb812016-06-01 20:07:22 -07001157
1158 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
1159 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001160 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001161 return;
1162 }
1163
1164 CXFA_Document* pDoc = pContext->GetDocument();
1165 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
1166
1167 CFX_ByteString szArgString;
1168 ValueToUTF8String(argOne.get(), szArgString);
1169 szArgString = szArgString.Mid(szArgString.Find('T', 0) + 1);
1170 if (szArgString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001171 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001172 return;
1173 }
1174
1175 CXFA_LocaleValue timeValue(
1176 XFA_VT_TIME, CFX_WideString::FromUTF8(szArgString.AsStringC()), pMgr);
1177 if (!timeValue.IsValid()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001178 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001179 return;
1180 }
1181
1182 CFX_Unitime uniTime = timeValue.GetTime();
1183 int32_t hour = uniTime.GetHour();
1184 int32_t min = uniTime.GetMinute();
1185 int32_t second = uniTime.GetSecond();
1186 int32_t milSecond = uniTime.GetMillisecond();
1187
1188 FX_TIMEZONE tzLocale;
tsepez211d4ed2016-11-11 17:23:48 -08001189 pMgr->GetDefLocale()->GetTimeZone(&tzLocale);
dsinclairdbdcb812016-06-01 20:07:22 -07001190
1191 // TODO(dsinclair): See if there is other time conversion code in pdfium and
1192 // consolidate.
1193 int32_t mins = hour * 60 + min;
1194 mins -= (tzLocale.tzHour * 60);
1195 while (mins > 1440)
1196 mins -= 1440;
1197 while (mins < 0)
1198 mins += 1440;
1199 hour = mins / 60;
1200 min = mins % 60;
dsinclairf27aeec2016-06-07 19:36:18 -07001201
1202 args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 +
1203 second * 1000 + milSecond + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001204}
dsinclair48d91dd2016-05-31 11:54:01 -07001205
1206// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001207void CXFA_FM2JSContext::LocalDateFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001208 const CFX_ByteStringC& szFuncName,
1209 CFXJSE_Arguments& args) {
1210 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001211 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001212 ToJSContext(pThis, nullptr)
1213 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"LocalDateFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001214 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001215 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001216
1217 int32_t iStyle = 0;
1218 if (argc > 0) {
1219 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001220 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001221 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001222 return;
1223 }
1224 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1225 if (iStyle > 4 || iStyle < 0)
1226 iStyle = 0;
1227 }
1228
1229 CFX_ByteString szLocal;
1230 if (argc > 1) {
1231 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001232 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001233 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001234 return;
1235 }
1236 ValueToUTF8String(argLocal.get(), szLocal);
1237 }
1238
1239 CFX_ByteString formatStr;
tsepezd19e9122016-11-02 15:43:18 -07001240 GetLocalDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, false);
dsinclairf27aeec2016-06-07 19:36:18 -07001241 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001242}
dsinclair48d91dd2016-05-31 11:54:01 -07001243
1244// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001245void CXFA_FM2JSContext::LocalTimeFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001246 const CFX_ByteStringC& szFuncName,
1247 CFXJSE_Arguments& args) {
1248 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001249 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001250 ToJSContext(pThis, nullptr)
1251 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"LocalTimeFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001252 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001253 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001254
1255 int32_t iStyle = 0;
1256 if (argc > 0) {
1257 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001258 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001259 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001260 return;
1261 }
1262 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1263 if (iStyle > 4 || iStyle < 0)
1264 iStyle = 0;
1265 }
1266
1267 CFX_ByteString szLocal;
1268 if (argc > 1) {
1269 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001270 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001271 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001272 return;
1273 }
1274 ValueToUTF8String(argLocal.get(), szLocal);
1275 }
1276
1277 CFX_ByteString formatStr;
tsepezd19e9122016-11-02 15:43:18 -07001278 GetLocalTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, false);
dsinclairf27aeec2016-06-07 19:36:18 -07001279 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001280}
dsinclair48d91dd2016-05-31 11:54:01 -07001281
1282// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001283void CXFA_FM2JSContext::Num2Date(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001284 const CFX_ByteStringC& szFuncName,
1285 CFXJSE_Arguments& args) {
1286 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001287 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001288 ToJSContext(pThis, nullptr)
1289 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2Date");
dsinclair2b6d64e2016-06-06 11:39:42 -07001290 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001291 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001292
1293 std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0);
1294 if (ValueIsNull(pThis, dateValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001295 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001296 return;
1297 }
1298 int32_t dDate = (int32_t)ValueToFloat(pThis, dateValue.get());
1299 if (dDate < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07001300 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001301 return;
1302 }
1303
1304 CFX_ByteString formatString;
1305 if (argc > 1) {
1306 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1307 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001308 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001309 return;
1310 }
1311 ValueToUTF8String(formatValue.get(), formatString);
1312 }
1313
1314 CFX_ByteString localString;
1315 if (argc > 2) {
1316 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1317 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001318 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001319 return;
1320 }
1321 ValueToUTF8String(localValue.get(), localString);
1322 }
1323
1324 int32_t iYear = 1900;
1325 int32_t iMonth = 1;
1326 int32_t iDay = 1;
1327 int32_t i = 0;
1328 while (dDate > 0) {
1329 if (iMonth == 2) {
1330 if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) {
1331 if (dDate > 29) {
1332 ++iMonth;
1333 if (iMonth > 12) {
1334 iMonth = 1;
1335 ++i;
1336 }
1337 iDay = 1;
1338 dDate -= 29;
1339 } else {
1340 iDay += static_cast<int32_t>(dDate) - 1;
1341 dDate = 0;
1342 }
1343 } else {
1344 if (dDate > 28) {
1345 ++iMonth;
1346 if (iMonth > 12) {
1347 iMonth = 1;
1348 ++i;
1349 }
1350 iDay = 1;
1351 dDate -= 28;
1352 } else {
1353 iDay += static_cast<int32_t>(dDate) - 1;
1354 dDate = 0;
1355 }
1356 }
1357 } else if (iMonth < 8) {
1358 if ((iMonth % 2 == 0)) {
1359 if (dDate > 30) {
1360 ++iMonth;
1361 if (iMonth > 12) {
1362 iMonth = 1;
1363 ++i;
1364 }
1365 iDay = 1;
1366 dDate -= 30;
1367 } else {
1368 iDay += static_cast<int32_t>(dDate) - 1;
1369 dDate = 0;
1370 }
1371 } else {
1372 if (dDate > 31) {
1373 ++iMonth;
1374 if (iMonth > 12) {
1375 iMonth = 1;
1376 ++i;
1377 }
1378 iDay = 1;
1379 dDate -= 31;
1380 } else {
1381 iDay += static_cast<int32_t>(dDate) - 1;
1382 dDate = 0;
1383 }
1384 }
1385 } else {
1386 if (iMonth % 2 != 0) {
1387 if (dDate > 30) {
1388 ++iMonth;
1389 if (iMonth > 12) {
1390 iMonth = 1;
1391 ++i;
1392 }
1393 iDay = 1;
1394 dDate -= 30;
1395 } else {
1396 iDay += static_cast<int32_t>(dDate) - 1;
1397 dDate = 0;
1398 }
1399 } else {
1400 if (dDate > 31) {
1401 ++iMonth;
1402 if (iMonth > 12) {
1403 iMonth = 1;
1404 ++i;
1405 }
1406 iDay = 1;
1407 dDate -= 31;
1408 } else {
1409 iDay += static_cast<int32_t>(dDate) - 1;
1410 dDate = 0;
1411 }
1412 }
1413 }
1414 }
1415
1416 CFX_ByteString szIsoDateString;
1417 szIsoDateString.Format("%d%02d%02d", iYear + i, iMonth, iDay);
1418 CFX_ByteString szLocalDateString;
1419 IsoDate2Local(pThis, szIsoDateString.AsStringC(), formatString.AsStringC(),
1420 localString.AsStringC(), szLocalDateString);
dsinclairf27aeec2016-06-07 19:36:18 -07001421 args.GetReturnValue()->SetString(szLocalDateString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001422}
dsinclair48d91dd2016-05-31 11:54:01 -07001423
1424// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001425void CXFA_FM2JSContext::Num2GMTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001426 const CFX_ByteStringC& szFuncName,
1427 CFXJSE_Arguments& args) {
1428 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001429 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001430 ToJSContext(pThis, nullptr)
1431 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2GMTime");
dsinclair2b6d64e2016-06-06 11:39:42 -07001432 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001433 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001434
1435 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001436 if (timeValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001437 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001438 return;
1439 }
1440 int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get());
1441 if (FXSYS_abs(iTime) < 1.0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001442 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001443 return;
1444 }
1445
1446 CFX_ByteString formatString;
1447 if (argc > 1) {
1448 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001449 if (formatValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001450 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001451 return;
1452 }
1453 ValueToUTF8String(formatValue.get(), formatString);
1454 }
1455
1456 CFX_ByteString localString;
1457 if (argc > 2) {
1458 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07001459 if (localValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001460 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001461 return;
1462 }
1463 ValueToUTF8String(localValue.get(), localString);
1464 }
1465
1466 CFX_ByteString szGMTTimeString;
1467 Num2AllTime(pThis, iTime, formatString.AsStringC(), localString.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07001468 true, szGMTTimeString);
dsinclairf27aeec2016-06-07 19:36:18 -07001469 args.GetReturnValue()->SetString(szGMTTimeString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001470}
dsinclair48d91dd2016-05-31 11:54:01 -07001471
1472// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001473void CXFA_FM2JSContext::Num2Time(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001474 const CFX_ByteStringC& szFuncName,
1475 CFXJSE_Arguments& args) {
1476 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001477 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001478 ToJSContext(pThis, nullptr)
1479 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2Time");
dsinclair2b6d64e2016-06-06 11:39:42 -07001480 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001481 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001482
1483 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001484 if (timeValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001485 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001486 return;
1487 }
1488 FX_FLOAT fTime = ValueToFloat(pThis, timeValue.get());
1489 if (FXSYS_fabs(fTime) < 1.0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001490 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001491 return;
1492 }
1493
1494 CFX_ByteString formatString;
1495 if (argc > 1) {
1496 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001497 if (formatValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001498 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001499 return;
1500 }
1501 ValueToUTF8String(formatValue.get(), formatString);
1502 }
1503
1504 CFX_ByteString localString;
1505 if (argc > 2) {
1506 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07001507 if (localValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001508 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001509 return;
1510 }
1511 ValueToUTF8String(localValue.get(), localString);
1512 }
1513
1514 CFX_ByteString szLocalTimeString;
1515 Num2AllTime(pThis, (int32_t)fTime, formatString.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07001516 localString.AsStringC(), false, szLocalTimeString);
dsinclairf27aeec2016-06-07 19:36:18 -07001517 args.GetReturnValue()->SetString(szLocalTimeString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001518}
dsinclair48d91dd2016-05-31 11:54:01 -07001519
1520// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001521void CXFA_FM2JSContext::Time(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001522 const CFX_ByteStringC& szFuncName,
1523 CFXJSE_Arguments& args) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001524 if (args.GetLength() != 0) {
dsinclair8f3074b2016-06-02 17:45:25 -07001525 ToJSContext(pThis, nullptr)
1526 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Time");
dsinclair2b6d64e2016-06-06 11:39:42 -07001527 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001528 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001529
1530 time_t now;
1531 time(&now);
1532
1533 struct tm* pGmt = gmtime(&now);
dsinclairf27aeec2016-06-07 19:36:18 -07001534 args.GetReturnValue()->SetInteger(
1535 (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000);
Dan Sinclair1770c022016-03-14 14:14:16 -04001536}
dsinclair48d91dd2016-05-31 11:54:01 -07001537
1538// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001539void CXFA_FM2JSContext::Time2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001540 const CFX_ByteStringC& szFuncName,
1541 CFXJSE_Arguments& args) {
1542 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001543 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001544 ToJSContext(pThis, nullptr)
1545 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Time2Num");
dsinclair2b6d64e2016-06-06 11:39:42 -07001546 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001547 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001548
1549 CFX_ByteString timeString;
1550 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
1551 if (ValueIsNull(pThis, timeValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001552 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001553 return;
1554 }
1555 ValueToUTF8String(timeValue.get(), timeString);
1556
1557 CFX_ByteString formatString;
1558 if (argc > 1) {
1559 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1560 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001561 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001562 return;
1563 }
1564 ValueToUTF8String(formatValue.get(), formatString);
1565 }
1566
1567 CFX_ByteString localString;
1568 if (argc > 2) {
1569 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1570 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001571 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001572 return;
1573 }
1574 ValueToUTF8String(localValue.get(), localString);
1575 }
1576
1577 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
1578 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
1579 IFX_Locale* pLocale = nullptr;
1580 if (localString.IsEmpty()) {
1581 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
1582 ASSERT(pThisNode);
1583
1584 CXFA_WidgetData widgetData(pThisNode);
1585 pLocale = widgetData.GetLocal();
1586 } else {
1587 pLocale = pMgr->GetLocaleByName(
1588 CFX_WideString::FromUTF8(localString.AsStringC()));
1589 }
1590
1591 CFX_WideString wsFormat;
1592 if (formatString.IsEmpty())
1593 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
1594 else
1595 wsFormat = CFX_WideString::FromUTF8(formatString.AsStringC());
1596
dsinclaircf7f3222016-06-08 20:34:02 -07001597 wsFormat = L"time{" + wsFormat + L"}";
dsinclair2b6d64e2016-06-06 11:39:42 -07001598 CXFA_LocaleValue localeValue(XFA_VT_TIME,
1599 CFX_WideString::FromUTF8(timeString.AsStringC()),
1600 wsFormat, pLocale, pMgr);
1601 if (!localeValue.IsValid()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001602 args.GetReturnValue()->SetInteger(0);
dsinclair2b6d64e2016-06-06 11:39:42 -07001603 return;
1604 }
1605
1606 CFX_Unitime uniTime = localeValue.GetTime();
1607 int32_t hour = uniTime.GetHour();
1608 int32_t min = uniTime.GetMinute();
1609 int32_t second = uniTime.GetSecond();
1610 int32_t milSecond = uniTime.GetMillisecond();
1611 int32_t mins = hour * 60 + min;
dsinclair2b6d64e2016-06-06 11:39:42 -07001612
tsepez211d4ed2016-11-11 17:23:48 -08001613 FX_TIMEZONE tz;
1614 CXFA_TimeZoneProvider provider;
1615 provider.GetTimeZone(&tz);
1616 mins -= (tz.tzHour * 60);
1617 while (mins > 1440)
1618 mins -= 1440;
1619
1620 while (mins < 0)
1621 mins += 1440;
1622
1623 hour = mins / 60;
1624 min = mins % 60;
dsinclairf27aeec2016-06-07 19:36:18 -07001625 args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 +
1626 second * 1000 + milSecond + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001627}
dsinclair48d91dd2016-05-31 11:54:01 -07001628
1629// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001630void CXFA_FM2JSContext::TimeFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001631 const CFX_ByteStringC& szFuncName,
1632 CFXJSE_Arguments& args) {
1633 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001634 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001635 ToJSContext(pThis, nullptr)
1636 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"TimeFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001637 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001638 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001639
1640 int32_t iStyle = 0;
1641 if (argc > 0) {
1642 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001643 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001644 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001645 return;
1646 }
1647 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1648 if (iStyle > 4 || iStyle < 0)
1649 iStyle = 0;
1650 }
1651
1652 CFX_ByteString szLocal;
1653 if (argc > 1) {
1654 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001655 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001656 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001657 return;
1658 }
1659 ValueToUTF8String(argLocal.get(), szLocal);
1660 }
1661
1662 CFX_ByteString formatStr;
1663 GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr);
dsinclairf27aeec2016-06-07 19:36:18 -07001664 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001665}
dsinclair48d91dd2016-05-31 11:54:01 -07001666
1667// static
tsepezd19e9122016-11-02 15:43:18 -07001668bool CXFA_FM2JSContext::IsIsoDateFormat(const FX_CHAR* pData,
1669 int32_t iLength,
1670 int32_t& iStyle,
1671 int32_t& iYear,
1672 int32_t& iMonth,
1673 int32_t& iDay) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001674 iYear = 0;
1675 iMonth = 1;
1676 iDay = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001677
1678 if (iLength < 4)
tsepezd19e9122016-11-02 15:43:18 -07001679 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001680
Dan Sinclair1770c022016-03-14 14:14:16 -04001681 FX_CHAR strYear[5];
1682 strYear[4] = '\0';
1683 for (int32_t i = 0; i < 4; ++i) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001684 if (pData[i] > '9' || pData[i] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001685 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001686
1687 strYear[i] = pData[i];
Dan Sinclair1770c022016-03-14 14:14:16 -04001688 }
1689 iYear = FXSYS_atoi(strYear);
1690 iStyle = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001691 if (iLength == 4)
tsepezd19e9122016-11-02 15:43:18 -07001692 return true;
dsinclair2b6d64e2016-06-06 11:39:42 -07001693
1694 iStyle = pData[4] == '-' ? 1 : 0;
1695
Dan Sinclair1770c022016-03-14 14:14:16 -04001696 FX_CHAR strTemp[3];
1697 strTemp[2] = '\0';
dsinclair2b6d64e2016-06-06 11:39:42 -07001698 int32_t iPosOff = iStyle == 0 ? 4 : 5;
1699 if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') ||
1700 (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0'))
tsepezd19e9122016-11-02 15:43:18 -07001701 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001702
1703 strTemp[0] = pData[iPosOff];
1704 strTemp[1] = pData[iPosOff + 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001705 iMonth = FXSYS_atoi(strTemp);
dsinclair2b6d64e2016-06-06 11:39:42 -07001706 if (iMonth > 12 || iMonth < 1)
tsepezd19e9122016-11-02 15:43:18 -07001707 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001708
Dan Sinclair1770c022016-03-14 14:14:16 -04001709 if (iStyle == 0) {
1710 iPosOff += 2;
dsinclair2b6d64e2016-06-06 11:39:42 -07001711 if (iLength == 6)
tsepezd19e9122016-11-02 15:43:18 -07001712 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001713 } else {
1714 iPosOff += 3;
dsinclair2b6d64e2016-06-06 11:39:42 -07001715 if (iLength == 7)
tsepezd19e9122016-11-02 15:43:18 -07001716 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001717 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001718 if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') ||
1719 (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0'))
tsepezd19e9122016-11-02 15:43:18 -07001720 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001721
1722 strTemp[0] = pData[iPosOff];
1723 strTemp[1] = pData[iPosOff + 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001724 iDay = FXSYS_atoi(strTemp);
dsinclair2b6d64e2016-06-06 11:39:42 -07001725 if (iPosOff + 2 < iLength)
tsepezd19e9122016-11-02 15:43:18 -07001726 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001727
Dan Sinclair1770c022016-03-14 14:14:16 -04001728 if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001729 if (iMonth == 2 && iDay > 29)
tsepezd19e9122016-11-02 15:43:18 -07001730 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001731 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07001732 if (iMonth == 2 && iDay > 28)
tsepezd19e9122016-11-02 15:43:18 -07001733 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001734 }
1735 if (iMonth != 2) {
1736 if (iMonth < 8) {
1737 if (iDay > (iMonth % 2 == 0 ? 30 : 31))
tsepezd19e9122016-11-02 15:43:18 -07001738 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001739 } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) {
tsepezd19e9122016-11-02 15:43:18 -07001740 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001741 }
1742 }
tsepezd19e9122016-11-02 15:43:18 -07001743 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001744}
dsinclair48d91dd2016-05-31 11:54:01 -07001745
1746// static
tsepezd19e9122016-11-02 15:43:18 -07001747bool CXFA_FM2JSContext::IsIsoTimeFormat(const FX_CHAR* pData,
1748 int32_t iLength,
1749 int32_t& iHour,
1750 int32_t& iMinute,
1751 int32_t& iSecond,
1752 int32_t& iMilliSecond,
1753 int32_t& iZoneHour,
1754 int32_t& iZoneMinute) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001755 iHour = 0;
1756 iMinute = 0;
1757 iSecond = 0;
1758 iMilliSecond = 0;
1759 iZoneHour = 0;
1760 iZoneMinute = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001761 if (!pData)
tsepezd19e9122016-11-02 15:43:18 -07001762 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001763
Dan Sinclair1770c022016-03-14 14:14:16 -04001764 FX_CHAR strTemp[3];
1765 strTemp[2] = '\0';
Dan Sinclair1770c022016-03-14 14:14:16 -04001766 int32_t iZone = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001767 int32_t i = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001768 while (i < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001769 if ((pData[i] > '9' || pData[i] < '0') && pData[i] != ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001770 iZone = i;
1771 break;
1772 }
1773 ++i;
1774 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001775 if (i == iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001776 iZone = iLength;
dsinclair2b6d64e2016-06-06 11:39:42 -07001777
Dan Sinclair1770c022016-03-14 14:14:16 -04001778 int32_t iPos = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001779 int32_t iIndex = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001780 while (iIndex < iZone) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001781 if (iIndex >= iZone)
Dan Sinclair1770c022016-03-14 14:14:16 -04001782 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07001783
1784 if (pData[iIndex] > '9' || pData[iIndex] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001785 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001786
1787 strTemp[0] = pData[iIndex];
1788 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001789 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001790
1791 strTemp[1] = pData[iIndex + 1];
1792 if (FXSYS_atoi(strTemp) > 60)
tsepezd19e9122016-11-02 15:43:18 -07001793 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001794
1795 if (pData[2] == ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001796 if (iPos == 0) {
1797 iHour = FXSYS_atoi(strTemp);
1798 ++iPos;
1799 } else if (iPos == 1) {
1800 iMinute = FXSYS_atoi(strTemp);
1801 ++iPos;
1802 } else {
1803 iSecond = FXSYS_atoi(strTemp);
1804 }
1805 iIndex += 3;
1806 } else {
1807 if (iPos == 0) {
1808 iHour = FXSYS_atoi(strTemp);
1809 ++iPos;
1810 } else if (iPos == 1) {
1811 iMinute = FXSYS_atoi(strTemp);
1812 ++iPos;
1813 } else if (iPos == 2) {
1814 iSecond = FXSYS_atoi(strTemp);
1815 ++iPos;
1816 }
1817 iIndex += 2;
1818 }
1819 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001820 if (pData[iIndex] == '.') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001821 ++iIndex;
weilidb444d22016-06-02 15:48:15 -07001822 FX_CHAR strSec[4];
1823 strSec[3] = '\0';
dsinclair2b6d64e2016-06-06 11:39:42 -07001824 if (pData[iIndex] > '9' || pData[iIndex] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001825 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001826
1827 strSec[0] = pData[iIndex];
1828 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001829 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001830
1831 strSec[1] = pData[iIndex + 1];
1832 if (pData[iIndex + 2] > '9' || pData[iIndex + 2] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001833 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001834
1835 strSec[2] = pData[iIndex + 2];
weilidb444d22016-06-02 15:48:15 -07001836 iMilliSecond = FXSYS_atoi(strSec);
Dan Sinclair1770c022016-03-14 14:14:16 -04001837 if (iMilliSecond > 100) {
1838 iMilliSecond = 0;
tsepezd19e9122016-11-02 15:43:18 -07001839 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001840 }
1841 iIndex += 3;
1842 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001843 if (pData[iIndex] == 'z' || pData[iIndex] == 'Z')
tsepezd19e9122016-11-02 15:43:18 -07001844 return true;
dsinclair2b6d64e2016-06-06 11:39:42 -07001845
Dan Sinclair1770c022016-03-14 14:14:16 -04001846 int32_t iSign = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001847 if (pData[iIndex] == '+') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001848 ++iIndex;
dsinclair2b6d64e2016-06-06 11:39:42 -07001849 } else if (pData[iIndex] == '-') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001850 iSign = -1;
1851 ++iIndex;
1852 }
1853 iPos = 0;
1854 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001855 if (iIndex >= iLength)
tsepezd19e9122016-11-02 15:43:18 -07001856 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001857 if (pData[iIndex] > '9' || pData[iIndex] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001858 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001859
1860 strTemp[0] = pData[iIndex];
1861 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
tsepezd19e9122016-11-02 15:43:18 -07001862 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001863
1864 strTemp[1] = pData[iIndex + 1];
1865 if (FXSYS_atoi(strTemp) > 60)
tsepezd19e9122016-11-02 15:43:18 -07001866 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001867
1868 if (pData[2] == ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001869 if (iPos == 0) {
1870 iZoneHour = FXSYS_atoi(strTemp);
1871 } else if (iPos == 1) {
1872 iZoneMinute = FXSYS_atoi(strTemp);
1873 }
1874 iIndex += 3;
1875 } else {
1876 if (!iPos) {
1877 iZoneHour = FXSYS_atoi(strTemp);
1878 ++iPos;
1879 } else if (iPos == 1) {
1880 iZoneMinute = FXSYS_atoi(strTemp);
1881 ++iPos;
1882 }
1883 iIndex += 2;
1884 }
1885 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001886 if (iIndex < iLength)
tsepezd19e9122016-11-02 15:43:18 -07001887 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001888
Dan Sinclair1770c022016-03-14 14:14:16 -04001889 iZoneHour *= iSign;
tsepezd19e9122016-11-02 15:43:18 -07001890 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001891}
dsinclair48d91dd2016-05-31 11:54:01 -07001892
1893// static
tsepezd19e9122016-11-02 15:43:18 -07001894bool CXFA_FM2JSContext::IsIsoDateTimeFormat(const FX_CHAR* pData,
1895 int32_t iLength,
1896 int32_t& iYear,
1897 int32_t& iMonth,
1898 int32_t& iDay,
1899 int32_t& iHour,
1900 int32_t& iMinute,
1901 int32_t& iSecond,
1902 int32_t& iMillionSecond,
1903 int32_t& iZoneHour,
1904 int32_t& iZoneMinute) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001905 iYear = 0;
1906 iMonth = 0;
1907 iDay = 0;
1908 iHour = 0;
1909 iMinute = 0;
1910 iSecond = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001911 if (!pData)
tsepezd19e9122016-11-02 15:43:18 -07001912 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001913
Dan Sinclair1770c022016-03-14 14:14:16 -04001914 int32_t iIndex = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001915 while (pData[iIndex] != 'T' && pData[iIndex] != 't') {
1916 if (iIndex >= iLength)
tsepezd19e9122016-11-02 15:43:18 -07001917 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001918 ++iIndex;
1919 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001920 if (iIndex != 8 && iIndex != 10)
tsepezd19e9122016-11-02 15:43:18 -07001921 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001922
Dan Sinclair1770c022016-03-14 14:14:16 -04001923 int32_t iStyle = -1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001924 if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay))
tsepezd19e9122016-11-02 15:43:18 -07001925 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001926 if (pData[iIndex] != 'T' && pData[iIndex] != 't')
tsepezd19e9122016-11-02 15:43:18 -07001927 return true;
dsinclair2b6d64e2016-06-06 11:39:42 -07001928
Dan Sinclair1770c022016-03-14 14:14:16 -04001929 ++iIndex;
1930 if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) &&
1931 (iLength - iIndex != 15)) {
tsepezd19e9122016-11-02 15:43:18 -07001932 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001933 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001934 if (!IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute,
1935 iSecond, iMillionSecond, iZoneHour, iZoneMinute)) {
tsepezd19e9122016-11-02 15:43:18 -07001936 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001937 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001938
tsepezd19e9122016-11-02 15:43:18 -07001939 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001940}
dsinclair48d91dd2016-05-31 11:54:01 -07001941
1942// static
tsepezd19e9122016-11-02 15:43:18 -07001943bool CXFA_FM2JSContext::Local2IsoDate(CFXJSE_Value* pThis,
1944 const CFX_ByteStringC& szDate,
1945 const CFX_ByteStringC& szFormat,
1946 const CFX_ByteStringC& szLocale,
1947 CFX_ByteString& strIsoDate) {
dsinclair8f3074b2016-06-02 17:45:25 -07001948 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07001949 if (!pDoc)
tsepezd19e9122016-11-02 15:43:18 -07001950 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001951
1952 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07001953 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001954 if (szLocale.IsEmpty()) {
1955 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07001956 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07001957
Dan Sinclair1770c022016-03-14 14:14:16 -04001958 CXFA_WidgetData widgetData(pThisNode);
1959 pLocale = widgetData.GetLocal();
1960 } else {
tsepezafe94302016-05-13 17:21:31 -07001961 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04001962 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001963 if (!pLocale)
tsepezd19e9122016-11-02 15:43:18 -07001964 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001965
Dan Sinclair1770c022016-03-14 14:14:16 -04001966 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07001967 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04001968 pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07001969 else
tsepez6fe7d212016-04-06 10:51:14 -07001970 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07001971
tsepez6fe7d212016-04-06 10:51:14 -07001972 CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate),
dsinclair2b6d64e2016-06-06 11:39:42 -07001973 wsFormat, pLocale, pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04001974 CFX_Unitime dt = widgetValue.GetDate();
1975 strIsoDate.Format("%4d-%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay());
tsepezd19e9122016-11-02 15:43:18 -07001976 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001977}
dsinclair48d91dd2016-05-31 11:54:01 -07001978
1979// static
tsepezd19e9122016-11-02 15:43:18 -07001980bool CXFA_FM2JSContext::Local2IsoTime(CFXJSE_Value* pThis,
1981 const CFX_ByteStringC& szTime,
1982 const CFX_ByteStringC& szFormat,
1983 const CFX_ByteStringC& szLocale,
1984 CFX_ByteString& strIsoTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07001985 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07001986 if (!pDoc)
tsepezd19e9122016-11-02 15:43:18 -07001987 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07001988
1989 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07001990 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001991 if (szLocale.IsEmpty()) {
1992 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07001993 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07001994
Dan Sinclair1770c022016-03-14 14:14:16 -04001995 CXFA_WidgetData widgetData(pThisNode);
1996 pLocale = widgetData.GetLocal();
1997 } else {
tsepezafe94302016-05-13 17:21:31 -07001998 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04001999 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002000 if (!pLocale)
tsepezd19e9122016-11-02 15:43:18 -07002001 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002002
Dan Sinclair1770c022016-03-14 14:14:16 -04002003 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002004 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002005 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002006 else
tsepez6fe7d212016-04-06 10:51:14 -07002007 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002008
dsinclaircf7f3222016-06-08 20:34:02 -07002009 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002010 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002011 wsFormat, pLocale, pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002012 CFX_Unitime utime = widgetValue.GetTime();
2013 strIsoTime.Format("%02d:%02d:%02d.%03d", utime.GetHour(), utime.GetMinute(),
2014 utime.GetSecond(), utime.GetMillisecond());
tsepezd19e9122016-11-02 15:43:18 -07002015 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04002016}
dsinclair48d91dd2016-05-31 11:54:01 -07002017
2018// static
tsepezd19e9122016-11-02 15:43:18 -07002019bool CXFA_FM2JSContext::IsoDate2Local(CFXJSE_Value* pThis,
2020 const CFX_ByteStringC& szDate,
2021 const CFX_ByteStringC& szFormat,
2022 const CFX_ByteStringC& szLocale,
2023 CFX_ByteString& strLocalDate) {
dsinclair8f3074b2016-06-02 17:45:25 -07002024 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002025 if (!pDoc)
tsepezd19e9122016-11-02 15:43:18 -07002026 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002027
2028 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002029 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002030 if (szLocale.IsEmpty()) {
2031 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002032 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002033 CXFA_WidgetData widgetData(pThisNode);
2034 pLocale = widgetData.GetLocal();
2035 } else {
tsepezafe94302016-05-13 17:21:31 -07002036 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002037 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002038 if (!pLocale)
tsepezd19e9122016-11-02 15:43:18 -07002039 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002040
Dan Sinclair1770c022016-03-14 14:14:16 -04002041 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002042 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002043 pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002044 else
tsepez6fe7d212016-04-06 10:51:14 -07002045 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002046
tsepez6fe7d212016-04-06 10:51:14 -07002047 CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate),
dsinclair2b6d64e2016-06-06 11:39:42 -07002048 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002049 CFX_WideString wsRet;
2050 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2051 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002052 strLocalDate = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
tsepezd19e9122016-11-02 15:43:18 -07002053 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04002054}
dsinclair48d91dd2016-05-31 11:54:01 -07002055
2056// static
tsepezd19e9122016-11-02 15:43:18 -07002057bool CXFA_FM2JSContext::IsoTime2Local(CFXJSE_Value* pThis,
2058 const CFX_ByteStringC& szTime,
2059 const CFX_ByteStringC& szFormat,
2060 const CFX_ByteStringC& szLocale,
2061 CFX_ByteString& strLocalTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07002062 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002063 if (!pDoc)
tsepezd19e9122016-11-02 15:43:18 -07002064 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002065
2066 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002067 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002068 if (szLocale.IsEmpty()) {
2069 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002070 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002071 CXFA_WidgetData widgetData(pThisNode);
2072 pLocale = widgetData.GetLocal();
2073 } else {
tsepezafe94302016-05-13 17:21:31 -07002074 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002075 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002076 if (!pLocale)
tsepezd19e9122016-11-02 15:43:18 -07002077 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002078
Dan Sinclair1770c022016-03-14 14:14:16 -04002079 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002080 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002081 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002082 else
tsepez6fe7d212016-04-06 10:51:14 -07002083 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002084
dsinclaircf7f3222016-06-08 20:34:02 -07002085 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002086 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002087 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002088 CFX_WideString wsRet;
2089 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2090 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002091 strLocalTime = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
tsepezd19e9122016-11-02 15:43:18 -07002092 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04002093}
dsinclair48d91dd2016-05-31 11:54:01 -07002094
2095// static
tsepezd19e9122016-11-02 15:43:18 -07002096bool CXFA_FM2JSContext::GetGMTTime(CFXJSE_Value* pThis,
2097 const CFX_ByteStringC& szTime,
2098 const CFX_ByteStringC& szFormat,
2099 const CFX_ByteStringC& szLocale,
2100 CFX_ByteString& strGMTTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07002101 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002102 if (!pDoc)
tsepezd19e9122016-11-02 15:43:18 -07002103 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002104
2105 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002106 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002107 if (szLocale.IsEmpty()) {
2108 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002109 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002110 CXFA_WidgetData widgetData(pThisNode);
2111 pLocale = widgetData.GetLocal();
2112 } else {
tsepezafe94302016-05-13 17:21:31 -07002113 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002114 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002115 if (!pLocale)
tsepezd19e9122016-11-02 15:43:18 -07002116 return false;
dsinclair2b6d64e2016-06-06 11:39:42 -07002117
Dan Sinclair1770c022016-03-14 14:14:16 -04002118 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002119 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002120 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002121 else
tsepez6fe7d212016-04-06 10:51:14 -07002122 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002123
dsinclaircf7f3222016-06-08 20:34:02 -07002124 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002125 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002126 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002127 CFX_WideString wsRet;
2128 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2129 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002130 strGMTTime = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
tsepezd19e9122016-11-02 15:43:18 -07002131 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04002132}
dsinclair48d91dd2016-05-31 11:54:01 -07002133
2134// static
Dan Sinclair1770c022016-03-14 14:14:16 -04002135int32_t CXFA_FM2JSContext::DateString2Num(const CFX_ByteStringC& szDateString) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002136 int32_t iLength = szDateString.GetLength();
Dan Sinclair1770c022016-03-14 14:14:16 -04002137 int32_t iYear = 0;
2138 int32_t iMonth = 0;
2139 int32_t iDay = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002140 if (iLength <= 10) {
dsinclair2b6d64e2016-06-06 11:39:42 -07002141 int32_t iStyle = -1;
2142 if (!IsIsoDateFormat(szDateString.c_str(), iLength, iStyle, iYear, iMonth,
2143 iDay)) {
2144 return 0;
2145 }
Dan Sinclair1770c022016-03-14 14:14:16 -04002146 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002147 int32_t iHour = 0;
2148 int32_t iMinute = 0;
2149 int32_t iSecond = 0;
2150 int32_t iMilliSecond = 0;
2151 int32_t iZoneHour = 0;
2152 int32_t iZoneMinute = 0;
2153 if (!IsIsoDateTimeFormat(szDateString.c_str(), iLength, iYear, iMonth, iDay,
2154 iHour, iMinute, iSecond, iMilliSecond, iZoneHour,
2155 iZoneMinute)) {
2156 return 0;
2157 }
Dan Sinclair1770c022016-03-14 14:14:16 -04002158 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002159
Dan Sinclair1770c022016-03-14 14:14:16 -04002160 FX_FLOAT dDays = 0;
2161 int32_t i = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07002162 if (iYear < 1900)
2163 return 0;
2164
2165 while (iYear - i >= 1900) {
2166 dDays +=
2167 ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400))
2168 ? 366
2169 : 365;
2170 ++i;
Dan Sinclair1770c022016-03-14 14:14:16 -04002171 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002172 i = 1;
2173 while (i < iMonth) {
2174 if (i == 2)
2175 dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28;
2176 else if (i <= 7)
2177 dDays += (i % 2 == 0) ? 30 : 31;
2178 else
2179 dDays += (i % 2 == 0) ? 31 : 30;
2180
2181 ++i;
2182 }
2183 i = 0;
2184 while (iDay - i > 0) {
2185 dDays += 1;
2186 ++i;
Dan Sinclair1770c022016-03-14 14:14:16 -04002187 }
2188 return (int32_t)dDays;
2189}
dsinclair0c268e92016-05-17 14:04:14 -07002190
dsinclair48d91dd2016-05-31 11:54:01 -07002191// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002192void CXFA_FM2JSContext::GetLocalDateFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002193 int32_t iStyle,
2194 const CFX_ByteStringC& szLocalStr,
2195 CFX_ByteString& strFormat,
tsepezd19e9122016-11-02 15:43:18 -07002196 bool bStandard) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002197 FX_LOCALEDATETIMESUBCATEGORY strStyle;
2198 switch (iStyle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002199 case 1:
2200 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short;
2201 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04002202 case 3:
2203 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long;
2204 break;
2205 case 4:
2206 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full;
2207 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07002208 case 0:
2209 case 2:
Dan Sinclair1770c022016-03-14 14:14:16 -04002210 default:
2211 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium;
2212 break;
2213 }
dsinclair8f3074b2016-06-02 17:45:25 -07002214 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002215 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002216 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002217
dsinclair48d91dd2016-05-31 11:54:01 -07002218 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002219 if (szLocalStr.IsEmpty()) {
2220 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002221 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07002222
Dan Sinclair1770c022016-03-14 14:14:16 -04002223 CXFA_WidgetData widgetData(pThisNode);
2224 pLocale = widgetData.GetLocal();
2225 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002226 pLocale = pDoc->GetLocalMgr()->GetLocaleByName(
2227 CFX_WideString::FromUTF8(szLocalStr));
Dan Sinclair1770c022016-03-14 14:14:16 -04002228 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002229 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002230 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002231
Dan Sinclair1770c022016-03-14 14:14:16 -04002232 CFX_WideString strRet;
2233 pLocale->GetDatePattern(strStyle, strRet);
2234 if (!bStandard) {
2235 CFX_WideString wsSymbols;
2236 pLocale->GetDateTimeSymbols(wsSymbols);
dsinclair0c268e92016-05-17 14:04:14 -07002237 AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Date);
Dan Sinclair1770c022016-03-14 14:14:16 -04002238 }
tsepezbd9748d2016-04-13 21:40:19 -07002239 strFormat = FX_UTF8Encode(strRet.c_str(), strRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002240}
dsinclair48d91dd2016-05-31 11:54:01 -07002241
2242// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002243void CXFA_FM2JSContext::GetLocalTimeFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002244 int32_t iStyle,
2245 const CFX_ByteStringC& szLocalStr,
2246 CFX_ByteString& strFormat,
tsepezd19e9122016-11-02 15:43:18 -07002247 bool bStandard) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002248 FX_LOCALEDATETIMESUBCATEGORY strStyle;
2249 switch (iStyle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002250 case 1:
2251 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short;
2252 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04002253 case 3:
2254 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long;
2255 break;
2256 case 4:
2257 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full;
2258 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07002259 case 0:
2260 case 2:
Dan Sinclair1770c022016-03-14 14:14:16 -04002261 default:
2262 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium;
2263 break;
2264 }
dsinclair8f3074b2016-06-02 17:45:25 -07002265 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002266 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002267 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002268
dsinclair48d91dd2016-05-31 11:54:01 -07002269 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002270 if (szLocalStr.IsEmpty()) {
2271 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002272 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07002273
Dan Sinclair1770c022016-03-14 14:14:16 -04002274 CXFA_WidgetData widgetData(pThisNode);
2275 pLocale = widgetData.GetLocal();
2276 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002277 pLocale = pDoc->GetLocalMgr()->GetLocaleByName(
2278 CFX_WideString::FromUTF8(szLocalStr));
Dan Sinclair1770c022016-03-14 14:14:16 -04002279 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002280 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002281 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002282
Dan Sinclair1770c022016-03-14 14:14:16 -04002283 CFX_WideString strRet;
2284 pLocale->GetTimePattern(strStyle, strRet);
2285 if (!bStandard) {
2286 CFX_WideString wsSymbols;
2287 pLocale->GetDateTimeSymbols(wsSymbols);
dsinclair0c268e92016-05-17 14:04:14 -07002288 AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Time);
Dan Sinclair1770c022016-03-14 14:14:16 -04002289 }
tsepezbd9748d2016-04-13 21:40:19 -07002290 strFormat = FX_UTF8Encode(strRet.c_str(), strRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002291}
dsinclair48d91dd2016-05-31 11:54:01 -07002292
2293// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002294void CXFA_FM2JSContext::GetStandardDateFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002295 int32_t iStyle,
2296 const CFX_ByteStringC& szLocalStr,
2297 CFX_ByteString& strFormat) {
tsepezd19e9122016-11-02 15:43:18 -07002298 GetLocalDateFormat(pThis, iStyle, szLocalStr, strFormat, true);
Dan Sinclair1770c022016-03-14 14:14:16 -04002299}
dsinclair48d91dd2016-05-31 11:54:01 -07002300
2301// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002302void CXFA_FM2JSContext::GetStandardTimeFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002303 int32_t iStyle,
2304 const CFX_ByteStringC& szLocalStr,
2305 CFX_ByteString& strFormat) {
tsepezd19e9122016-11-02 15:43:18 -07002306 GetLocalTimeFormat(pThis, iStyle, szLocalStr, strFormat, true);
Dan Sinclair1770c022016-03-14 14:14:16 -04002307}
dsinclair48d91dd2016-05-31 11:54:01 -07002308
2309// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002310void CXFA_FM2JSContext::Num2AllTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002311 int32_t iTime,
2312 const CFX_ByteStringC& szFormat,
2313 const CFX_ByteStringC& szLocale,
tsepezd19e9122016-11-02 15:43:18 -07002314 bool bGM,
Dan Sinclair1770c022016-03-14 14:14:16 -04002315 CFX_ByteString& strTime) {
2316 int32_t iHour = 0;
2317 int32_t iMin = 0;
2318 int32_t iSec = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002319 iHour = static_cast<int>(iTime) / 3600000;
2320 iMin = (static_cast<int>(iTime) - iHour * 3600000) / 60000;
2321 iSec = (static_cast<int>(iTime) - iHour * 3600000 - iMin * 60000) / 1000;
dsinclair2b6d64e2016-06-06 11:39:42 -07002322
Dan Sinclair1770c022016-03-14 14:14:16 -04002323 if (!bGM) {
dsinclair2b6d64e2016-06-06 11:39:42 -07002324 int32_t iZoneHour = 0;
2325 int32_t iZoneMin = 0;
2326 int32_t iZoneSec = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002327 GetLocalTimeZone(iZoneHour, iZoneMin, iZoneSec);
2328 iHour += iZoneHour;
2329 iMin += iZoneMin;
2330 iSec += iZoneSec;
2331 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002332
tsepezd19e9122016-11-02 15:43:18 -07002333 bool iRet = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04002334 CFX_ByteString strIsoTime;
2335 strIsoTime.Format("%02d:%02d:%02d", iHour, iMin, iSec);
2336 if (bGM) {
tsepez4c3debb2016-04-08 12:20:38 -07002337 iRet =
dsinclair12a6b0c2016-05-26 11:14:08 -07002338 GetGMTTime(pThis, strIsoTime.AsStringC(), szFormat, szLocale, strTime);
Dan Sinclair1770c022016-03-14 14:14:16 -04002339 } else {
dsinclair12a6b0c2016-05-26 11:14:08 -07002340 iRet = IsoTime2Local(pThis, strIsoTime.AsStringC(), szFormat, szLocale,
tsepez28f97ff2016-04-04 16:41:35 -07002341 strTime);
Dan Sinclair1770c022016-03-14 14:14:16 -04002342 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002343 if (!iRet)
Dan Sinclair1770c022016-03-14 14:14:16 -04002344 strTime = "";
Dan Sinclair1770c022016-03-14 14:14:16 -04002345}
2346
dsinclair48d91dd2016-05-31 11:54:01 -07002347// static
Dan Sinclair1770c022016-03-14 14:14:16 -04002348void CXFA_FM2JSContext::GetLocalTimeZone(int32_t& iHour,
2349 int32_t& iMin,
2350 int32_t& iSec) {
2351 time_t now;
2352 time(&now);
dsinclair2b6d64e2016-06-06 11:39:42 -07002353
Dan Sinclair1770c022016-03-14 14:14:16 -04002354 struct tm* pGmt = gmtime(&now);
Dan Sinclair1770c022016-03-14 14:14:16 -04002355 struct tm* pLocal = localtime(&now);
dsinclair2b6d64e2016-06-06 11:39:42 -07002356 iHour = pLocal->tm_hour - pGmt->tm_hour;
2357 iMin = pLocal->tm_min - pGmt->tm_min;
2358 iSec = pLocal->tm_sec - pGmt->tm_sec;
Dan Sinclair1770c022016-03-14 14:14:16 -04002359}
dsinclair48d91dd2016-05-31 11:54:01 -07002360
2361// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002362void CXFA_FM2JSContext::Apr(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002363 const CFX_ByteStringC& szFuncName,
2364 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002365 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002366 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002367 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Apr");
dsinclair96a05f42016-06-07 06:48:02 -07002368 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002369 }
dsinclair96a05f42016-06-07 06:48:02 -07002370
2371 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2372 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2373 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2374 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2375 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002376 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002377 return;
2378 }
2379
2380 FX_DOUBLE nPrincipal = ValueToDouble(pThis, argOne.get());
2381 FX_DOUBLE nPayment = ValueToDouble(pThis, argTwo.get());
2382 FX_DOUBLE nPeriods = ValueToDouble(pThis, argThree.get());
2383 if (nPrincipal <= 0 || nPayment <= 0 || nPeriods <= 0) {
2384 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2385 return;
2386 }
2387
2388 FX_DOUBLE r =
2389 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal);
2390 FX_DOUBLE nTemp = 1;
2391 for (int32_t i = 0; i < nPeriods; ++i)
2392 nTemp *= (1 + r);
2393
2394 FX_DOUBLE nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2395 while (fabs(nRet) > kFinancialPrecision) {
2396 FX_DOUBLE nDerivative =
2397 ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) -
2398 (r * nTemp * nPeriods * (nTemp / (1 + r)))) /
2399 ((nTemp - 1) * (nTemp - 1));
2400 if (nDerivative == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -07002401 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002402 return;
2403 }
2404
2405 r = r - nRet / nDerivative;
2406 nTemp = 1;
2407 for (int32_t i = 0; i < nPeriods; ++i) {
2408 nTemp *= (1 + r);
2409 }
2410 nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2411 }
dsinclairf27aeec2016-06-07 19:36:18 -07002412 args.GetReturnValue()->SetDouble(r * 12);
Dan Sinclair1770c022016-03-14 14:14:16 -04002413}
dsinclair48d91dd2016-05-31 11:54:01 -07002414
2415// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002416void CXFA_FM2JSContext::CTerm(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002417 const CFX_ByteStringC& szFuncName,
2418 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002419 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002420 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002421 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"CTerm");
dsinclair96a05f42016-06-07 06:48:02 -07002422 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002423 }
dsinclair96a05f42016-06-07 06:48:02 -07002424
2425 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2426 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2427 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2428 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2429 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002430 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002431 return;
2432 }
2433
2434 FX_FLOAT nRate = ValueToFloat(pThis, argOne.get());
2435 FX_FLOAT nFutureValue = ValueToFloat(pThis, argTwo.get());
2436 FX_FLOAT nInitAmount = ValueToFloat(pThis, argThree.get());
2437 if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) {
2438 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2439 return;
2440 }
2441
dsinclairf27aeec2016-06-07 19:36:18 -07002442 args.GetReturnValue()->SetFloat(
2443 FXSYS_log((FX_FLOAT)(nFutureValue / nInitAmount)) /
2444 FXSYS_log((FX_FLOAT)(1 + nRate)));
Dan Sinclair1770c022016-03-14 14:14:16 -04002445}
dsinclair48d91dd2016-05-31 11:54:01 -07002446
2447// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002448void CXFA_FM2JSContext::FV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002449 const CFX_ByteStringC& szFuncName,
2450 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002451 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002452 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002453 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"FV");
dsinclair96a05f42016-06-07 06:48:02 -07002454 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002455 }
dsinclair96a05f42016-06-07 06:48:02 -07002456
2457 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2458 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2459 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2460 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2461 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002462 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002463 return;
2464 }
2465
2466 FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get());
2467 FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get());
2468 FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get());
2469 if ((nRate < 0) || (nPeriod <= 0) || (nAmount <= 0)) {
2470 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2471 return;
2472 }
2473
2474 FX_DOUBLE dResult = 0;
2475 if (nRate) {
2476 FX_DOUBLE nTemp = 1;
2477 for (int i = 0; i < nPeriod; ++i) {
2478 nTemp *= 1 + nRate;
2479 }
2480 dResult = nAmount * (nTemp - 1) / nRate;
2481 } else {
2482 dResult = nAmount * nPeriod;
2483 }
2484
dsinclairf27aeec2016-06-07 19:36:18 -07002485 args.GetReturnValue()->SetDouble(dResult);
Dan Sinclair1770c022016-03-14 14:14:16 -04002486}
dsinclair48d91dd2016-05-31 11:54:01 -07002487
2488// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002489void CXFA_FM2JSContext::IPmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002490 const CFX_ByteStringC& szFuncName,
2491 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002492 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002493 if (args.GetLength() != 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07002494 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"IPmt");
dsinclair96a05f42016-06-07 06:48:02 -07002495 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002496 }
dsinclair96a05f42016-06-07 06:48:02 -07002497
2498 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2499 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2500 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2501 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
2502 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
2503 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2504 ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) ||
2505 ValueIsNull(pThis, argFive.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002506 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002507 return;
2508 }
2509
2510 FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get());
2511 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2512 FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get());
2513 FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get());
2514 FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get());
2515 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2516 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2517 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2518 return;
2519 }
2520
2521 FX_FLOAT nRateOfMonth = nRate / 12;
2522 int32_t iNums = (int32_t)(
2523 (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) -
2524 FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2525 FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth)));
2526 int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums);
2527
2528 if (nPayment < nPrincipalAmount * nRateOfMonth) {
dsinclairf27aeec2016-06-07 19:36:18 -07002529 args.GetReturnValue()->SetFloat(0);
dsinclair96a05f42016-06-07 06:48:02 -07002530 return;
2531 }
2532
2533 int32_t i = 0;
2534 for (i = 0; i < nFirstMonth - 1; ++i)
2535 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2536
2537 FX_FLOAT nSum = 0;
2538 for (; i < iEnd; ++i) {
2539 nSum += nPrincipalAmount * nRateOfMonth;
2540 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2541 }
dsinclairf27aeec2016-06-07 19:36:18 -07002542 args.GetReturnValue()->SetFloat(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002543}
dsinclair48d91dd2016-05-31 11:54:01 -07002544
2545// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002546void CXFA_FM2JSContext::NPV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002547 const CFX_ByteStringC& szFuncName,
2548 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002549 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002550 int32_t argc = args.GetLength();
dsinclair96a05f42016-06-07 06:48:02 -07002551 if (argc < 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002552 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"NPV");
dsinclair96a05f42016-06-07 06:48:02 -07002553 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002554 }
dsinclair96a05f42016-06-07 06:48:02 -07002555
2556 std::vector<std::unique_ptr<CFXJSE_Value>> argValues;
2557 for (int32_t i = 0; i < argc; i++) {
2558 argValues.push_back(GetSimpleValue(pThis, args, i));
2559 if (ValueIsNull(pThis, argValues[i].get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002560 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002561 return;
2562 }
2563 }
2564
2565 FX_DOUBLE nRate = ValueToDouble(pThis, argValues[0].get());
2566 if (nRate <= 0) {
2567 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2568 return;
2569 }
2570
2571 std::vector<FX_DOUBLE> data(argc - 1);
2572 for (int32_t i = 1; i < argc; i++)
2573 data.push_back(ValueToDouble(pThis, argValues[i].get()));
2574
2575 FX_DOUBLE nSum = 0;
2576 int32_t iIndex = 0;
2577 for (int32_t i = 0; i < argc - 1; i++) {
2578 FX_DOUBLE nTemp = 1;
2579 for (int32_t j = 0; j <= i; j++)
2580 nTemp *= 1 + nRate;
2581
2582 FX_DOUBLE nNum = data[iIndex++];
2583 nSum += nNum / nTemp;
2584 }
dsinclairf27aeec2016-06-07 19:36:18 -07002585 args.GetReturnValue()->SetDouble(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002586}
dsinclair48d91dd2016-05-31 11:54:01 -07002587
2588// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002589void CXFA_FM2JSContext::Pmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002590 const CFX_ByteStringC& szFuncName,
2591 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002592 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002593 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002594 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Pmt");
dsinclair96a05f42016-06-07 06:48:02 -07002595 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002596 }
dsinclair96a05f42016-06-07 06:48:02 -07002597
2598 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2599 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2600 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2601 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2602 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002603 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002604 return;
2605 }
2606
2607 FX_FLOAT nPrincipal = ValueToFloat(pThis, argOne.get());
2608 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2609 FX_FLOAT nPeriods = ValueToFloat(pThis, argThree.get());
2610 if ((nPrincipal <= 0) || (nRate <= 0) || (nPeriods <= 0)) {
2611 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2612 return;
2613 }
2614
2615 FX_FLOAT nTmp = 1 + nRate;
2616 FX_FLOAT nSum = nTmp;
2617 for (int32_t i = 0; i < nPeriods - 1; ++i)
2618 nSum *= nTmp;
2619
dsinclairf27aeec2016-06-07 19:36:18 -07002620 args.GetReturnValue()->SetFloat((nPrincipal * nRate * nSum) / (nSum - 1));
Dan Sinclair1770c022016-03-14 14:14:16 -04002621}
dsinclair48d91dd2016-05-31 11:54:01 -07002622
2623// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002624void CXFA_FM2JSContext::PPmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002625 const CFX_ByteStringC& szFuncName,
2626 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002627 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002628 if (args.GetLength() != 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07002629 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"PPmt");
dsinclair96a05f42016-06-07 06:48:02 -07002630 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002631 }
dsinclair96a05f42016-06-07 06:48:02 -07002632
2633 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2634 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2635 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2636 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
2637 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
2638 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2639 ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) ||
2640 ValueIsNull(pThis, argFive.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002641 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002642 return;
2643 }
2644
2645 FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get());
2646 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2647 FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get());
2648 FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get());
2649 FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get());
2650 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2651 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2652 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2653 return;
2654 }
2655
2656 FX_FLOAT nRateOfMonth = nRate / 12;
2657 int32_t iNums = (int32_t)(
2658 (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) -
2659 FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2660 FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth)));
2661 int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums);
2662 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2663 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2664 return;
2665 }
2666
2667 int32_t i = 0;
2668 for (i = 0; i < nFirstMonth - 1; ++i)
2669 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2670
2671 FX_FLOAT nTemp = 0;
2672 FX_FLOAT nSum = 0;
2673 for (; i < iEnd; ++i) {
2674 nTemp = nPayment - nPrincipalAmount * nRateOfMonth;
2675 nSum += nTemp;
2676 nPrincipalAmount -= nTemp;
2677 }
dsinclairf27aeec2016-06-07 19:36:18 -07002678 args.GetReturnValue()->SetFloat(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002679}
dsinclair48d91dd2016-05-31 11:54:01 -07002680
2681// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002682void CXFA_FM2JSContext::PV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002683 const CFX_ByteStringC& szFuncName,
2684 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002685 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002686 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002687 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"PV");
dsinclair96a05f42016-06-07 06:48:02 -07002688 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002689 }
dsinclair96a05f42016-06-07 06:48:02 -07002690
2691 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2692 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2693 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2694 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2695 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002696 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002697 return;
2698 }
2699
2700 FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get());
2701 FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get());
2702 FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get());
2703 if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) {
2704 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2705 return;
2706 }
2707
2708 FX_DOUBLE nTemp = 1;
2709 for (int32_t i = 0; i < nPeriod; ++i)
2710 nTemp *= 1 + nRate;
2711
2712 nTemp = 1 / nTemp;
dsinclairf27aeec2016-06-07 19:36:18 -07002713 args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate));
Dan Sinclair1770c022016-03-14 14:14:16 -04002714}
dsinclair48d91dd2016-05-31 11:54:01 -07002715
2716// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002717void CXFA_FM2JSContext::Rate(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002718 const CFX_ByteStringC& szFuncName,
2719 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002720 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002721 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002722 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Rate");
dsinclair96a05f42016-06-07 06:48:02 -07002723 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002724 }
dsinclair96a05f42016-06-07 06:48:02 -07002725
2726 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2727 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2728 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2729 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2730 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002731 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002732 return;
2733 }
2734
2735 FX_FLOAT nFuture = ValueToFloat(pThis, argOne.get());
2736 FX_FLOAT nPresent = ValueToFloat(pThis, argTwo.get());
2737 FX_FLOAT nTotalNumber = ValueToFloat(pThis, argThree.get());
2738 if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) {
2739 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2740 return;
2741 }
2742
dsinclairf27aeec2016-06-07 19:36:18 -07002743 args.GetReturnValue()->SetFloat(
2744 FXSYS_pow((FX_FLOAT)(nFuture / nPresent), (FX_FLOAT)(1 / nTotalNumber)) -
2745 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04002746}
dsinclair48d91dd2016-05-31 11:54:01 -07002747
2748// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002749void CXFA_FM2JSContext::Term(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002750 const CFX_ByteStringC& szFuncName,
2751 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002752 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002753 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002754 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Term");
dsinclair96a05f42016-06-07 06:48:02 -07002755 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002756 }
dsinclair96a05f42016-06-07 06:48:02 -07002757
2758 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2759 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2760 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2761 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2762 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002763 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002764 return;
2765 }
2766
2767 FX_FLOAT nMount = ValueToFloat(pThis, argOne.get());
2768 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2769 FX_FLOAT nFuture = ValueToFloat(pThis, argThree.get());
2770 if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) {
2771 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2772 return;
2773 }
2774
dsinclairf27aeec2016-06-07 19:36:18 -07002775 args.GetReturnValue()->SetFloat(
2776 FXSYS_log((FX_FLOAT)(nFuture / nMount * nRate) + 1) /
2777 FXSYS_log((FX_FLOAT)(1 + nRate)));
Dan Sinclair1770c022016-03-14 14:14:16 -04002778}
dsinclair48d91dd2016-05-31 11:54:01 -07002779
2780// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002781void CXFA_FM2JSContext::Choose(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002782 const CFX_ByteStringC& szFuncName,
2783 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002784 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002785 int32_t argc = args.GetLength();
dsinclair96a05f42016-06-07 06:48:02 -07002786 if (argc < 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07002787 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Choose");
dsinclair96a05f42016-06-07 06:48:02 -07002788 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002789 }
dsinclair96a05f42016-06-07 06:48:02 -07002790
2791 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
2792 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002793 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002794 return;
2795 }
2796
2797 int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get());
2798 if (iIndex < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07002799 args.GetReturnValue()->SetString("");
dsinclair96a05f42016-06-07 06:48:02 -07002800 return;
2801 }
2802
tsepezd19e9122016-11-02 15:43:18 -07002803 bool bFound = false;
2804 bool bStopCounterFlags = false;
dsinclair96a05f42016-06-07 06:48:02 -07002805 int32_t iArgIndex = 1;
2806 int32_t iValueIndex = 0;
2807 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
2808 while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) {
2809 std::unique_ptr<CFXJSE_Value> argIndexValue = args.GetValue(iArgIndex);
dsinclair769b1372016-06-08 13:12:41 -07002810 if (argIndexValue->IsArray()) {
dsinclair96a05f42016-06-07 06:48:02 -07002811 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07002812 argIndexValue->GetObjectProperty("length", lengthValue.get());
2813 int32_t iLength = lengthValue->ToInteger();
dsinclair96a05f42016-06-07 06:48:02 -07002814 if (iLength > 3)
tsepezd19e9122016-11-02 15:43:18 -07002815 bStopCounterFlags = true;
dsinclair96a05f42016-06-07 06:48:02 -07002816
2817 iValueIndex += (iLength - 2);
2818 if (iValueIndex >= iIndex) {
2819 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
2820 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
2821 std::unique_ptr<CFXJSE_Value> newPropertyValue(
2822 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07002823 argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get());
2824 argIndexValue->GetObjectPropertyByIdx(
2825 (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07002826 if (propertyValue->IsNull()) {
dsinclair96a05f42016-06-07 06:48:02 -07002827 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
2828 } else {
dsinclair2f5582f2016-06-09 11:48:23 -07002829 jsObjectValue->GetObjectProperty(
2830 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair96a05f42016-06-07 06:48:02 -07002831 }
2832 CFX_ByteString bsChoosed;
2833 ValueToUTF8String(newPropertyValue.get(), bsChoosed);
dsinclairf27aeec2016-06-07 19:36:18 -07002834 args.GetReturnValue()->SetString(bsChoosed.AsStringC());
tsepezd19e9122016-11-02 15:43:18 -07002835 bFound = true;
dsinclair96a05f42016-06-07 06:48:02 -07002836 }
2837 } else {
2838 iValueIndex++;
2839 if (iValueIndex == iIndex) {
2840 CFX_ByteString bsChoosed;
2841 ValueToUTF8String(argIndexValue.get(), bsChoosed);
dsinclairf27aeec2016-06-07 19:36:18 -07002842 args.GetReturnValue()->SetString(bsChoosed.AsStringC());
tsepezd19e9122016-11-02 15:43:18 -07002843 bFound = true;
dsinclair96a05f42016-06-07 06:48:02 -07002844 }
2845 }
2846 iArgIndex++;
2847 }
2848 if (!bFound)
dsinclairf27aeec2016-06-07 19:36:18 -07002849 args.GetReturnValue()->SetString("");
Dan Sinclair1770c022016-03-14 14:14:16 -04002850}
dsinclair48d91dd2016-05-31 11:54:01 -07002851
2852// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002853void CXFA_FM2JSContext::Exists(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002854 const CFX_ByteStringC& szFuncName,
2855 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002856 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07002857 ToJSContext(pThis, nullptr)
2858 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Exists");
dsinclair96a05f42016-06-07 06:48:02 -07002859 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002860 }
dsinclair769b1372016-06-08 13:12:41 -07002861 args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject());
Dan Sinclair1770c022016-03-14 14:14:16 -04002862}
dsinclair48d91dd2016-05-31 11:54:01 -07002863
2864// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002865void CXFA_FM2JSContext::HasValue(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002866 const CFX_ByteStringC& szFuncName,
2867 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002868 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07002869 ToJSContext(pThis, nullptr)
2870 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"HasValue");
dsinclair96a05f42016-06-07 06:48:02 -07002871 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002872 }
dsinclair96a05f42016-06-07 06:48:02 -07002873
2874 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07002875 if (!argOne->IsString()) {
2876 args.GetReturnValue()->SetInteger(argOne->IsNumber() ||
2877 argOne->IsBoolean());
dsinclair96a05f42016-06-07 06:48:02 -07002878 return;
2879 }
2880
dsinclair2f5582f2016-06-09 11:48:23 -07002881 CFX_ByteString valueStr = argOne->ToString();
dsinclair96a05f42016-06-07 06:48:02 -07002882 valueStr.TrimLeft();
dsinclairf27aeec2016-06-07 19:36:18 -07002883 args.GetReturnValue()->SetInteger(!valueStr.IsEmpty());
Dan Sinclair1770c022016-03-14 14:14:16 -04002884}
dsinclair48d91dd2016-05-31 11:54:01 -07002885
2886// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002887void CXFA_FM2JSContext::Oneof(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002888 const CFX_ByteStringC& szFuncName,
2889 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002890 if (args.GetLength() < 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07002891 ToJSContext(pThis, nullptr)
2892 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Oneof");
dsinclair96a05f42016-06-07 06:48:02 -07002893 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002894 }
dsinclair96a05f42016-06-07 06:48:02 -07002895
tsepezd19e9122016-11-02 15:43:18 -07002896 bool bFlags = false;
dsinclair96a05f42016-06-07 06:48:02 -07002897 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2898 CFXJSE_Value** parametersValue = nullptr;
2899 int32_t iCount = 0;
2900 unfoldArgs(pThis, args, parametersValue, iCount, 1);
2901 for (int32_t i = 0; i < iCount; i++) {
2902 if (simpleValueCompare(pThis, argOne.get(), parametersValue[i])) {
tsepezd19e9122016-11-02 15:43:18 -07002903 bFlags = true;
dsinclair96a05f42016-06-07 06:48:02 -07002904 break;
2905 }
2906 }
2907 for (int32_t i = 0; i < iCount; i++)
2908 delete parametersValue[i];
2909 FX_Free(parametersValue);
2910
dsinclairf27aeec2016-06-07 19:36:18 -07002911 args.GetReturnValue()->SetInteger(bFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04002912}
dsinclair48d91dd2016-05-31 11:54:01 -07002913
2914// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002915void CXFA_FM2JSContext::Within(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002916 const CFX_ByteStringC& szFuncName,
2917 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07002918 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07002919 ToJSContext(pThis, nullptr)
2920 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Within");
dsinclair759de382016-06-07 14:10:16 -07002921 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002922 }
dsinclair759de382016-06-07 14:10:16 -07002923
2924 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07002925 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07002926 args.GetReturnValue()->SetUndefined();
dsinclair759de382016-06-07 14:10:16 -07002927 return;
2928 }
2929
2930 std::unique_ptr<CFXJSE_Value> argLow = GetSimpleValue(pThis, args, 1);
2931 std::unique_ptr<CFXJSE_Value> argHigh = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07002932 if (argOne->IsNumber()) {
dsinclair759de382016-06-07 14:10:16 -07002933 FX_FLOAT oneNumber = ValueToFloat(pThis, argOne.get());
2934 FX_FLOAT lowNumber = ValueToFloat(pThis, argLow.get());
2935 FX_FLOAT heightNumber = ValueToFloat(pThis, argHigh.get());
dsinclairf27aeec2016-06-07 19:36:18 -07002936 args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) &&
2937 (oneNumber <= heightNumber));
dsinclair759de382016-06-07 14:10:16 -07002938 return;
2939 }
2940
2941 CFX_ByteString oneString;
2942 CFX_ByteString lowString;
2943 CFX_ByteString heightString;
2944 ValueToUTF8String(argOne.get(), oneString);
2945 ValueToUTF8String(argLow.get(), lowString);
2946 ValueToUTF8String(argHigh.get(), heightString);
dsinclairf27aeec2016-06-07 19:36:18 -07002947 args.GetReturnValue()->SetInteger(
2948 (oneString.Compare(lowString.AsStringC()) >= 0) &&
2949 (oneString.Compare(heightString.AsStringC()) <= 0));
Dan Sinclair1770c022016-03-14 14:14:16 -04002950}
dsinclair48d91dd2016-05-31 11:54:01 -07002951
2952// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002953void CXFA_FM2JSContext::If(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002954 const CFX_ByteStringC& szFuncName,
2955 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07002956 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07002957 ToJSContext(pThis, nullptr)
2958 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"If");
dsinclair759de382016-06-07 14:10:16 -07002959 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002960 }
dsinclair759de382016-06-07 14:10:16 -07002961
dsinclairf27aeec2016-06-07 19:36:18 -07002962 args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean()
2963 ? GetSimpleValue(pThis, args, 1).get()
2964 : GetSimpleValue(pThis, args, 2).get());
Dan Sinclair1770c022016-03-14 14:14:16 -04002965}
dsinclair48d91dd2016-05-31 11:54:01 -07002966
2967// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002968void CXFA_FM2JSContext::Eval(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002969 const CFX_ByteStringC& szFuncName,
2970 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002971 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair759de382016-06-07 14:10:16 -07002972 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07002973 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Eval");
dsinclair759de382016-06-07 14:10:16 -07002974 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002975 }
dsinclair759de382016-06-07 14:10:16 -07002976
2977 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
2978 std::unique_ptr<CFXJSE_Value> scriptValue = GetSimpleValue(pThis, args, 0);
2979 CFX_ByteString utf8ScriptString;
2980 ValueToUTF8String(scriptValue.get(), utf8ScriptString);
2981 if (utf8ScriptString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07002982 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07002983 return;
2984 }
2985
2986 CFX_WideTextBuf wsJavaScriptBuf;
2987 CFX_WideString wsError;
2988 CXFA_FM2JSContext::Translate(
2989 CFX_WideString::FromUTF8(utf8ScriptString.AsStringC()).AsStringC(),
2990 wsJavaScriptBuf, wsError);
dsinclair769b1372016-06-08 13:12:41 -07002991 std::unique_ptr<CFXJSE_Context> pNewContext(
2992 CFXJSE_Context::Create(pIsolate, nullptr, nullptr));
dsinclair759de382016-06-07 14:10:16 -07002993
2994 std::unique_ptr<CFXJSE_Value> returnValue(new CFXJSE_Value(pIsolate));
2995 CFX_WideString javaScript(wsJavaScriptBuf.AsStringC());
dsinclair769b1372016-06-08 13:12:41 -07002996 pNewContext->ExecuteScript(
dsinclair759de382016-06-07 14:10:16 -07002997 FX_UTF8Encode(javaScript.c_str(), javaScript.GetLength()).c_str(),
2998 returnValue.get());
2999
dsinclairf27aeec2016-06-07 19:36:18 -07003000 args.GetReturnValue()->Assign(returnValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04003001}
dsinclair48d91dd2016-05-31 11:54:01 -07003002
3003// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003004void CXFA_FM2JSContext::Ref(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003005 const CFX_ByteStringC& szFuncName,
3006 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07003007 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07003008 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
dsinclair759de382016-06-07 14:10:16 -07003009 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07003010 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ref");
dsinclair759de382016-06-07 14:10:16 -07003011 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003012 }
dsinclair759de382016-06-07 14:10:16 -07003013
3014 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
dsinclair769b1372016-06-08 13:12:41 -07003015 if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() &&
3016 !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) {
dsinclair759de382016-06-07 14:10:16 -07003017 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
3018 return;
3019 }
3020
dsinclair769b1372016-06-08 13:12:41 -07003021 if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003022 args.GetReturnValue()->Assign(argOne.get());
dsinclair759de382016-06-07 14:10:16 -07003023 return;
3024 }
3025
3026 CFXJSE_Value* rgValues[3];
3027 for (int32_t i = 0; i < 3; i++)
3028 rgValues[i] = new CFXJSE_Value(pIsolate);
3029
3030 int intVal = 3;
dsinclair769b1372016-06-08 13:12:41 -07003031 if (argOne->IsNull()) {
3032 // TODO(dsinclair): Why is this 4 when the others are all 3?
dsinclair759de382016-06-07 14:10:16 -07003033 intVal = 4;
dsinclairf27aeec2016-06-07 19:36:18 -07003034 rgValues[2]->SetNull();
dsinclair769b1372016-06-08 13:12:41 -07003035 } else if (argOne->IsArray()) {
dsinclair759de382016-06-07 14:10:16 -07003036#ifndef NDEBUG
3037 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07003038 argOne->GetObjectProperty("length", lengthValue.get());
3039 ASSERT(lengthValue->ToInteger() >= 3);
dsinclair759de382016-06-07 14:10:16 -07003040#endif
3041
3042 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
3043 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07003044 argOne->GetObjectPropertyByIdx(1, propertyValue.get());
3045 argOne->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07003046 if (!propertyValue->IsNull() || jsObjectValue->IsNull()) {
dsinclair759de382016-06-07 14:10:16 -07003047 for (int32_t i = 0; i < 3; i++)
3048 delete rgValues[i];
3049
3050 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
3051 return;
3052 }
3053
dsinclairf27aeec2016-06-07 19:36:18 -07003054 rgValues[2]->Assign(jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07003055 } else if (argOne->IsObject()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003056 rgValues[2]->Assign(argOne.get());
dsinclair759de382016-06-07 14:10:16 -07003057 }
3058
dsinclairf27aeec2016-06-07 19:36:18 -07003059 rgValues[0]->SetInteger(intVal);
3060 rgValues[1]->SetNull();
3061 args.GetReturnValue()->SetArray(3, rgValues);
dsinclair759de382016-06-07 14:10:16 -07003062
3063 for (int32_t i = 0; i < 3; i++)
3064 delete rgValues[i];
Dan Sinclair1770c022016-03-14 14:14:16 -04003065}
dsinclair48d91dd2016-05-31 11:54:01 -07003066
3067// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003068void CXFA_FM2JSContext::UnitType(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003069 const CFX_ByteStringC& szFuncName,
3070 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07003071 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07003072 ToJSContext(pThis, nullptr)
3073 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"UnitType");
dsinclair759de382016-06-07 14:10:16 -07003074 return;
3075 }
3076
3077 std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07003078 if (unitspanValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003079 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003080 return;
3081 }
3082
3083 CFX_ByteString unitspanString;
3084 ValueToUTF8String(unitspanValue.get(), unitspanString);
3085 if (unitspanString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003086 args.GetReturnValue()->SetString("in");
dsinclair759de382016-06-07 14:10:16 -07003087 return;
3088 }
3089
3090 enum XFA_FM2JS_VALUETYPE_ParserStatus {
3091 VALUETYPE_START,
3092 VALUETYPE_HAVEINVALIDCHAR,
3093 VALUETYPE_HAVEDIGIT,
3094 VALUETYPE_HAVEDIGITWHITE,
3095 VALUETYPE_ISCM,
3096 VALUETYPE_ISMM,
3097 VALUETYPE_ISPT,
3098 VALUETYPE_ISMP,
3099 VALUETYPE_ISIN,
3100 };
3101 unitspanString.MakeLower();
3102 CFX_WideString wsTypeString =
3103 CFX_WideString::FromUTF8(unitspanString.AsStringC());
3104 const FX_WCHAR* pData = wsTypeString.c_str();
3105 int32_t u = 0;
3106 int32_t uLen = wsTypeString.GetLength();
3107 while (IsWhitespace(pData[u]))
3108 u++;
3109
3110 XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START;
3111 FX_WCHAR typeChar;
3112 // TODO(dsinclair): Cleanup this parser, figure out what the various checks
3113 // are for.
3114 while (u < uLen) {
3115 typeChar = pData[u];
3116 if (IsWhitespace(typeChar)) {
3117 if (eParserStatus != VALUETYPE_HAVEDIGIT &&
3118 eParserStatus != VALUETYPE_HAVEDIGITWHITE) {
3119 eParserStatus = VALUETYPE_ISIN;
3120 break;
3121 }
3122 eParserStatus = VALUETYPE_HAVEDIGITWHITE;
3123 } else if ((typeChar >= '0' && typeChar <= '9') || typeChar == '-' ||
3124 typeChar == '.') {
3125 if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) {
3126 eParserStatus = VALUETYPE_ISIN;
3127 break;
3128 }
3129 eParserStatus = VALUETYPE_HAVEDIGIT;
3130 } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) {
3131 FX_WCHAR nextChar = pData[u + 1];
3132 if ((eParserStatus == VALUETYPE_START ||
3133 eParserStatus == VALUETYPE_HAVEDIGIT ||
3134 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3135 (nextChar > '9' || nextChar < '0') && nextChar != '.' &&
3136 nextChar != '-') {
3137 eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT;
3138 break;
3139 }
3140 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3141 } else if (typeChar == 'm' && (u + 1 < uLen)) {
3142 FX_WCHAR nextChar = pData[u + 1];
3143 if ((eParserStatus == VALUETYPE_START ||
3144 eParserStatus == VALUETYPE_HAVEDIGIT ||
3145 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3146 (nextChar > '9' || nextChar < '0') && nextChar != '.' &&
3147 nextChar != '-') {
3148 eParserStatus = VALUETYPE_ISMM;
3149 if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' &&
3150 pData[u + 2] == 'l' && pData[u + 3] == 'l' &&
3151 pData[u + 4] == 'i' && pData[u + 5] == 'p')) {
3152 eParserStatus = VALUETYPE_ISMP;
3153 }
3154 break;
3155 }
3156 } else {
3157 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3158 }
3159 u++;
3160 }
3161 switch (eParserStatus) {
3162 case VALUETYPE_ISCM:
dsinclairf27aeec2016-06-07 19:36:18 -07003163 args.GetReturnValue()->SetString("cm");
dsinclair759de382016-06-07 14:10:16 -07003164 break;
3165 case VALUETYPE_ISMM:
dsinclairf27aeec2016-06-07 19:36:18 -07003166 args.GetReturnValue()->SetString("mm");
dsinclair759de382016-06-07 14:10:16 -07003167 break;
3168 case VALUETYPE_ISPT:
dsinclairf27aeec2016-06-07 19:36:18 -07003169 args.GetReturnValue()->SetString("pt");
dsinclair759de382016-06-07 14:10:16 -07003170 break;
3171 case VALUETYPE_ISMP:
dsinclairf27aeec2016-06-07 19:36:18 -07003172 args.GetReturnValue()->SetString("mp");
dsinclair759de382016-06-07 14:10:16 -07003173 break;
3174 default:
dsinclairf27aeec2016-06-07 19:36:18 -07003175 args.GetReturnValue()->SetString("in");
dsinclair759de382016-06-07 14:10:16 -07003176 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04003177 }
3178}
dsinclair48d91dd2016-05-31 11:54:01 -07003179
3180// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003181void CXFA_FM2JSContext::UnitValue(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003182 const CFX_ByteStringC& szFuncName,
3183 CFXJSE_Arguments& args) {
3184 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003185 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07003186 ToJSContext(pThis, nullptr)
3187 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"UnitValue");
dsinclair759de382016-06-07 14:10:16 -07003188 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003189 }
dsinclair759de382016-06-07 14:10:16 -07003190
3191 std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07003192 if (unitspanValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003193 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003194 return;
3195 }
3196
3197 CFX_ByteString unitspanString;
3198 ValueToUTF8String(unitspanValue.get(), unitspanString);
3199 const FX_CHAR* pData = unitspanString.c_str();
3200 if (!pData) {
dsinclairf27aeec2016-06-07 19:36:18 -07003201 args.GetReturnValue()->SetInteger(0);
dsinclair759de382016-06-07 14:10:16 -07003202 return;
3203 }
3204
3205 int32_t u = 0;
3206 while (IsWhitespace(pData[u]))
3207 ++u;
3208
3209 while (u < unitspanString.GetLength()) {
3210 if ((pData[u] > '9' || pData[u] < '0') && pData[u] != '.' &&
3211 pData[u] != '-') {
3212 break;
3213 }
3214 ++u;
3215 }
3216
3217 FX_CHAR* pTemp = nullptr;
3218 FX_DOUBLE dFirstNumber = strtod(pData, &pTemp);
3219 while (IsWhitespace(pData[u]))
3220 ++u;
3221
3222 int32_t uLen = unitspanString.GetLength();
3223 CFX_ByteString strFirstUnit;
3224 while (u < uLen) {
3225 if (pData[u] == ' ')
3226 break;
3227
3228 strFirstUnit += pData[u];
3229 ++u;
3230 }
3231 strFirstUnit.MakeLower();
3232
3233 CFX_ByteString strUnit;
3234 if (argc > 1) {
3235 std::unique_ptr<CFXJSE_Value> unitValue = GetSimpleValue(pThis, args, 1);
3236 CFX_ByteString unitTempString;
3237 ValueToUTF8String(unitValue.get(), unitTempString);
3238 const FX_CHAR* pChar = unitTempString.c_str();
3239 int32_t uVal = 0;
3240 while (IsWhitespace(pChar[uVal]))
3241 ++uVal;
3242
3243 while (uVal < unitTempString.GetLength()) {
3244 if ((pChar[uVal] > '9' || pChar[uVal] < '0') && pChar[uVal] != '.') {
3245 break;
3246 }
3247 ++uVal;
3248 }
3249 while (IsWhitespace(pChar[uVal]))
3250 ++uVal;
3251
3252 int32_t uValLen = unitTempString.GetLength();
3253 while (uVal < uValLen) {
3254 if (pChar[uVal] == ' ')
3255 break;
3256
3257 strUnit += pChar[uVal];
3258 ++uVal;
3259 }
3260 strUnit.MakeLower();
3261 } else {
3262 strUnit = strFirstUnit;
3263 }
3264
3265 FX_DOUBLE dResult = 0;
3266 if (strFirstUnit == "in" || strFirstUnit == "inches") {
3267 if (strUnit == "mm" || strUnit == "millimeters")
3268 dResult = dFirstNumber * 25.4;
3269 else if (strUnit == "cm" || strUnit == "centimeters")
3270 dResult = dFirstNumber * 2.54;
3271 else if (strUnit == "pt" || strUnit == "points")
3272 dResult = dFirstNumber / 72;
3273 else if (strUnit == "mp" || strUnit == "millipoints")
3274 dResult = dFirstNumber / 72000;
3275 else
3276 dResult = dFirstNumber;
3277 } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") {
3278 if (strUnit == "mm" || strUnit == "millimeters")
3279 dResult = dFirstNumber;
3280 else if (strUnit == "cm" || strUnit == "centimeters")
3281 dResult = dFirstNumber / 10;
3282 else if (strUnit == "pt" || strUnit == "points")
3283 dResult = dFirstNumber / 25.4 / 72;
3284 else if (strUnit == "mp" || strUnit == "millipoints")
3285 dResult = dFirstNumber / 25.4 / 72000;
3286 else
3287 dResult = dFirstNumber / 25.4;
3288 } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") {
3289 if (strUnit == "mm" || strUnit == "millimeters")
3290 dResult = dFirstNumber * 10;
3291 else if (strUnit == "cm" || strUnit == "centimeters")
3292 dResult = dFirstNumber;
3293 else if (strUnit == "pt" || strUnit == "points")
3294 dResult = dFirstNumber / 2.54 / 72;
3295 else if (strUnit == "mp" || strUnit == "millipoints")
3296 dResult = dFirstNumber / 2.54 / 72000;
3297 else
3298 dResult = dFirstNumber / 2.54;
3299 } else if (strFirstUnit == "pt" || strFirstUnit == "points") {
3300 if (strUnit == "mm" || strUnit == "millimeters")
3301 dResult = dFirstNumber / 72 * 25.4;
3302 else if (strUnit == "cm" || strUnit == "centimeters")
3303 dResult = dFirstNumber / 72 * 2.54;
3304 else if (strUnit == "pt" || strUnit == "points")
3305 dResult = dFirstNumber;
3306 else if (strUnit == "mp" || strUnit == "millipoints")
3307 dResult = dFirstNumber * 1000;
3308 else
3309 dResult = dFirstNumber / 72;
3310 } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") {
3311 if (strUnit == "mm" || strUnit == "millimeters")
3312 dResult = dFirstNumber / 72000 * 25.4;
3313 else if (strUnit == "cm" || strUnit == "centimeters")
3314 dResult = dFirstNumber / 72000 * 2.54;
3315 else if (strUnit == "pt" || strUnit == "points")
3316 dResult = dFirstNumber / 1000;
3317 else if (strUnit == "mp" || strUnit == "millipoints")
3318 dResult = dFirstNumber;
3319 else
3320 dResult = dFirstNumber / 72000;
3321 }
dsinclairf27aeec2016-06-07 19:36:18 -07003322 args.GetReturnValue()->SetDouble(dResult);
Dan Sinclair1770c022016-03-14 14:14:16 -04003323}
dsinclair48d91dd2016-05-31 11:54:01 -07003324
3325// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003326void CXFA_FM2JSContext::At(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003327 const CFX_ByteStringC& szFuncName,
3328 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07003329 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07003330 ToJSContext(pThis, nullptr)
3331 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"At");
dsinclair759de382016-06-07 14:10:16 -07003332 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003333 }
dsinclair759de382016-06-07 14:10:16 -07003334
3335 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3336 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3337 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003338 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003339 return;
3340 }
3341
3342 CFX_ByteString stringTwo;
3343 ValueToUTF8String(argTwo.get(), stringTwo);
3344 if (stringTwo.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003345 args.GetReturnValue()->SetInteger(1);
dsinclair759de382016-06-07 14:10:16 -07003346 return;
3347 }
3348
3349 CFX_ByteString stringOne;
3350 ValueToUTF8String(argOne.get(), stringOne);
3351 FX_STRSIZE iPosition = stringOne.Find(stringTwo.AsStringC());
dsinclairf27aeec2016-06-07 19:36:18 -07003352 args.GetReturnValue()->SetInteger(iPosition + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04003353}
dsinclair48d91dd2016-05-31 11:54:01 -07003354
3355// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003356void CXFA_FM2JSContext::Concat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003357 const CFX_ByteStringC& szFuncName,
3358 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003359 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003360 if (argc < 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07003361 ToJSContext(pThis, nullptr)
3362 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Concat");
dsinclair759de382016-06-07 14:10:16 -07003363 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003364 }
dsinclair759de382016-06-07 14:10:16 -07003365
3366 CFX_ByteString resultString;
tsepezd19e9122016-11-02 15:43:18 -07003367 bool bAllNull = true;
dsinclair759de382016-06-07 14:10:16 -07003368 for (int32_t i = 0; i < argc; i++) {
3369 std::unique_ptr<CFXJSE_Value> value = GetSimpleValue(pThis, args, i);
3370 if (ValueIsNull(pThis, value.get()))
3371 continue;
3372
tsepezd19e9122016-11-02 15:43:18 -07003373 bAllNull = false;
dsinclair759de382016-06-07 14:10:16 -07003374
3375 CFX_ByteString valueStr;
3376 ValueToUTF8String(value.get(), valueStr);
3377 resultString += valueStr;
3378 }
3379
3380 if (bAllNull) {
dsinclairf27aeec2016-06-07 19:36:18 -07003381 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003382 return;
3383 }
3384
dsinclairf27aeec2016-06-07 19:36:18 -07003385 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003386}
dsinclair48d91dd2016-05-31 11:54:01 -07003387
3388// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003389void CXFA_FM2JSContext::Decode(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003390 const CFX_ByteStringC& szFuncName,
3391 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003392 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003393 if (argc < 1 || argc > 2) {
3394 ToJSContext(pThis, nullptr)
3395 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Decode");
3396 return;
3397 }
3398
Dan Sinclair1770c022016-03-14 14:14:16 -04003399 if (argc == 1) {
dsinclair86fad992016-05-31 11:34:04 -07003400 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3401 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003402 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003403 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003404 }
dsinclair759de382016-06-07 14:10:16 -07003405
3406 CFX_ByteString toDecodeString;
3407 ValueToUTF8String(argOne.get(), toDecodeString);
3408 CFX_ByteTextBuf resultBuf;
3409 DecodeURL(toDecodeString.AsStringC(), resultBuf);
dsinclairf27aeec2016-06-07 19:36:18 -07003410 args.GetReturnValue()->SetString(resultBuf.AsStringC());
dsinclair759de382016-06-07 14:10:16 -07003411 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003412 }
dsinclair759de382016-06-07 14:10:16 -07003413
3414 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3415 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3416 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003417 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003418 return;
3419 }
3420
3421 CFX_ByteString toDecodeString;
3422 ValueToUTF8String(argOne.get(), toDecodeString);
3423
3424 CFX_ByteString identifyString;
3425 ValueToUTF8String(argTwo.get(), identifyString);
3426
3427 CFX_ByteTextBuf resultBuf;
3428 if (identifyString.EqualNoCase("html"))
3429 DecodeHTML(toDecodeString.AsStringC(), resultBuf);
3430 else if (identifyString.EqualNoCase("xml"))
3431 DecodeXML(toDecodeString.AsStringC(), resultBuf);
3432 else
3433 DecodeURL(toDecodeString.AsStringC(), resultBuf);
3434
dsinclairf27aeec2016-06-07 19:36:18 -07003435 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003436}
dsinclair48d91dd2016-05-31 11:54:01 -07003437
3438// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003439void CXFA_FM2JSContext::DecodeURL(const CFX_ByteStringC& szURLString,
3440 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003441 CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString);
tsepezbd9748d2016-04-13 21:40:19 -07003442 const FX_WCHAR* pData = wsURLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003443 int32_t i = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04003444 CFX_WideTextBuf wsResultBuf;
dsinclair759de382016-06-07 14:10:16 -07003445 while (i < wsURLString.GetLength()) {
3446 FX_WCHAR ch = pData[i];
3447 if ('%' != ch) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003448 wsResultBuf.AppendChar(ch);
dsinclair759de382016-06-07 14:10:16 -07003449 ++i;
3450 continue;
Dan Sinclair1770c022016-03-14 14:14:16 -04003451 }
dsinclair759de382016-06-07 14:10:16 -07003452
3453 FX_WCHAR chTemp = 0;
3454 int32_t iCount = 0;
3455 while (iCount < 2) {
3456 ++i;
3457 ch = pData[i];
3458 if (ch <= '9' && ch >= '0') {
3459 // TODO(dsinclair): Premultiply and add rather then scale.
3460 chTemp += (ch - '0') * (!iCount ? 16 : 1);
3461 } else if (ch <= 'F' && ch >= 'A') {
3462 chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1);
3463 } else if (ch <= 'f' && ch >= 'a') {
3464 chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1);
3465 } else {
3466 wsResultBuf.Clear();
3467 return;
3468 }
3469 ++iCount;
3470 }
3471 wsResultBuf.AppendChar(chTemp);
Dan Sinclair1770c022016-03-14 14:14:16 -04003472 ++i;
3473 }
3474 wsResultBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003475
Dan Sinclair1770c022016-03-14 14:14:16 -04003476 szResultString.Clear();
3477 szResultString << FX_UTF8Encode(wsResultBuf.GetBuffer(),
tsepez28f97ff2016-04-04 16:41:35 -07003478 wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003479 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003480}
dsinclair48d91dd2016-05-31 11:54:01 -07003481
3482// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003483void CXFA_FM2JSContext::DecodeHTML(const CFX_ByteStringC& szHTMLString,
3484 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003485 CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(szHTMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003486 FX_WCHAR strString[9];
3487 int32_t iStrIndex = 0;
3488 int32_t iLen = wsHTMLString.GetLength();
3489 int32_t i = 0;
3490 int32_t iCode = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003491 const FX_WCHAR* pData = wsHTMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003492 CFX_WideTextBuf wsResultBuf;
3493 while (i < iLen) {
dsinclair759de382016-06-07 14:10:16 -07003494 FX_WCHAR ch = pData[i];
3495 if (ch != '&') {
Dan Sinclair1770c022016-03-14 14:14:16 -04003496 wsResultBuf.AppendChar(ch);
3497 ++i;
3498 continue;
3499 }
dsinclair759de382016-06-07 14:10:16 -07003500
3501 ++i;
3502 ch = pData[i];
3503 if (ch == '#') {
3504 ++i;
3505 ch = pData[i];
3506 if (ch != 'x' && ch != 'X') {
3507 wsResultBuf.Clear();
3508 return;
3509 }
3510
3511 ++i;
3512 ch = pData[i];
3513 if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') ||
3514 (ch <= 'F' && ch >= 'A')) {
3515 while (ch != ';' && i < iLen) {
3516 if (ch >= '0' && ch <= '9') {
3517 iCode += ch - '0';
3518 } else if (ch <= 'f' && ch >= 'a') {
3519 iCode += ch - 'a' + 10;
3520 } else if (ch <= 'F' && ch >= 'A') {
3521 iCode += ch - 'A' + 10;
3522 } else {
3523 wsResultBuf.Clear();
3524 return;
3525 }
3526 ++i;
3527 // TODO(dsinclair): Postmultiply seems wrong, start at zero
3528 // and pre-multiply then can remove the post divide.
3529 iCode *= 16;
3530 ch = pData[i];
3531 }
3532 iCode /= 16;
3533 }
3534 } else {
3535 while (ch != ';' && i < iLen) {
3536 strString[iStrIndex++] = ch;
3537 ++i;
3538 ch = pData[i];
3539 }
3540 strString[iStrIndex] = 0;
3541 }
Dan Sinclair1770c022016-03-14 14:14:16 -04003542 uint32_t iData = 0;
3543 if (HTMLSTR2Code(strString, iData)) {
3544 wsResultBuf.AppendChar((FX_WCHAR)iData);
3545 } else {
3546 wsResultBuf.AppendChar(iCode);
3547 }
3548 iStrIndex = 0;
3549 strString[iStrIndex] = 0;
3550 ++i;
3551 }
3552 wsResultBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003553
Dan Sinclair1770c022016-03-14 14:14:16 -04003554 szResultString.Clear();
3555 szResultString << FX_UTF8Encode(wsResultBuf.GetBuffer(),
tsepez28f97ff2016-04-04 16:41:35 -07003556 wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003557 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003558}
dsinclair48d91dd2016-05-31 11:54:01 -07003559
3560// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003561void CXFA_FM2JSContext::DecodeXML(const CFX_ByteStringC& szXMLString,
3562 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003563 CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003564 FX_WCHAR strString[9];
3565 int32_t iStrIndex = 0;
3566 int32_t iLen = wsXMLString.GetLength();
3567 int32_t i = 0;
3568 int32_t iCode = 0;
3569 FX_WCHAR ch = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003570 const FX_WCHAR* pData = wsXMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003571 CFX_WideTextBuf wsXMLBuf;
3572 while (i < iLen) {
dsinclair2b6d64e2016-06-06 11:39:42 -07003573 ch = pData[i];
dsinclair759de382016-06-07 14:10:16 -07003574 if (ch != '&') {
Dan Sinclair1770c022016-03-14 14:14:16 -04003575 wsXMLBuf.AppendChar(ch);
3576 ++i;
3577 continue;
3578 }
dsinclair759de382016-06-07 14:10:16 -07003579
3580 // TODO(dsinclair): This is very similar to DecodeHTML, can they be
3581 // combined?
3582 ++i;
3583 ch = pData[i];
3584 if (ch == '#') {
3585 ++i;
3586 ch = pData[i];
3587 if (ch != 'x' && ch != 'X') {
3588 wsXMLBuf.Clear();
3589 return;
3590 }
3591
3592 ++i;
3593 ch = pData[i];
3594 if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') ||
3595 (ch <= 'F' && ch >= 'A')) {
3596 while (ch != ';') {
3597 if (ch >= '0' && ch <= '9') {
3598 iCode += ch - '0';
3599 } else if (ch <= 'f' && ch >= 'a') {
3600 iCode += ch - 'a' + 10;
3601 } else if (ch <= 'F' && ch >= 'A') {
3602 iCode += ch - 'A' + 10;
3603 } else {
3604 wsXMLBuf.Clear();
3605 return;
3606 }
3607 ++i;
3608 iCode *= 16;
3609 ch = pData[i];
3610 }
3611 iCode /= 16;
3612 }
3613 } else {
3614 while (ch != ';' && i < iLen) {
3615 strString[iStrIndex++] = ch;
3616 ++i;
3617 ch = pData[i];
3618 }
3619 strString[iStrIndex] = 0;
3620 }
3621
Dan Sinclair1770c022016-03-14 14:14:16 -04003622 const FX_WCHAR* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"};
3623 int32_t iIndex = 0;
3624 while (iIndex < 5) {
3625 if (FXSYS_memcmp(strString, strName[iIndex],
3626 FXSYS_wcslen(strName[iIndex])) == 0) {
3627 break;
3628 }
3629 ++iIndex;
3630 }
3631 switch (iIndex) {
3632 case 0:
3633 wsXMLBuf.AppendChar('"');
3634 break;
3635 case 1:
3636 wsXMLBuf.AppendChar('&');
3637 break;
3638 case 2:
3639 wsXMLBuf.AppendChar('\'');
3640 break;
3641 case 3:
3642 wsXMLBuf.AppendChar('<');
3643 break;
3644 case 4:
3645 wsXMLBuf.AppendChar('>');
3646 break;
3647 default:
3648 wsXMLBuf.AppendChar(iCode);
3649 break;
3650 }
3651 iStrIndex = 0;
3652 strString[iStrIndex] = 0;
3653 ++i;
3654 iCode = 0;
3655 }
3656 wsXMLBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003657
Dan Sinclair1770c022016-03-14 14:14:16 -04003658 szResultString.Clear();
tsepez28f97ff2016-04-04 16:41:35 -07003659 szResultString << FX_UTF8Encode(wsXMLBuf.GetBuffer(), wsXMLBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003660 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003661}
dsinclair48d91dd2016-05-31 11:54:01 -07003662
3663// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003664void CXFA_FM2JSContext::Encode(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003665 const CFX_ByteStringC& szFuncName,
3666 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003667 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07003668 if (argc < 1 || argc > 2) {
3669 ToJSContext(pThis, nullptr)
3670 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Encode");
3671 return;
3672 }
3673
Dan Sinclair1770c022016-03-14 14:14:16 -04003674 if (argc == 1) {
dsinclair86fad992016-05-31 11:34:04 -07003675 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3676 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003677 args.GetReturnValue()->SetNull();
dsinclaircf7f3222016-06-08 20:34:02 -07003678 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003679 }
dsinclaircf7f3222016-06-08 20:34:02 -07003680
3681 CFX_ByteString toEncodeString;
3682 ValueToUTF8String(argOne.get(), toEncodeString);
3683 CFX_ByteTextBuf resultBuf;
3684 EncodeURL(toEncodeString.AsStringC(), resultBuf);
3685 args.GetReturnValue()->SetString(resultBuf.AsStringC());
3686 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003687 }
dsinclaircf7f3222016-06-08 20:34:02 -07003688
3689 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3690 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3691 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
3692 args.GetReturnValue()->SetNull();
3693 return;
3694 }
3695
3696 CFX_ByteString toEncodeString;
3697 ValueToUTF8String(argOne.get(), toEncodeString);
3698 CFX_ByteString identifyString;
3699 ValueToUTF8String(argTwo.get(), identifyString);
3700 CFX_ByteTextBuf resultBuf;
3701 if (identifyString.EqualNoCase("html"))
3702 EncodeHTML(toEncodeString.AsStringC(), resultBuf);
3703 else if (identifyString.EqualNoCase("xml"))
3704 EncodeXML(toEncodeString.AsStringC(), resultBuf);
3705 else
3706 EncodeURL(toEncodeString.AsStringC(), resultBuf);
3707
3708 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003709}
dsinclair48d91dd2016-05-31 11:54:01 -07003710
3711// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003712void CXFA_FM2JSContext::EncodeURL(const CFX_ByteStringC& szURLString,
3713 CFX_ByteTextBuf& szResultBuf) {
tsepez6fe7d212016-04-06 10:51:14 -07003714 CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003715 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003716 FX_WCHAR strEncode[4];
3717 strEncode[0] = '%';
3718 strEncode[3] = 0;
3719 FX_WCHAR strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}',
3720 '|', '\\', '^', '~', '[', ']', '`'};
3721 FX_WCHAR strReserved[] = {';', '/', '?', ':', '@', '=', '&'};
3722 FX_WCHAR strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','};
3723 const FX_WCHAR* strCode = L"0123456789abcdef";
dsinclaircf7f3222016-06-08 20:34:02 -07003724 for (int32_t u = 0; u < wsURLString.GetLength(); ++u) {
3725 FX_WCHAR ch = wsURLString.GetAt(u);
Dan Sinclair1770c022016-03-14 14:14:16 -04003726 int32_t i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003727 int32_t iCount = FX_ArraySize(strUnsafe);
Dan Sinclair1770c022016-03-14 14:14:16 -04003728 while (i < iCount) {
3729 if (ch == strUnsafe[i]) {
3730 int32_t iIndex = ch / 16;
3731 strEncode[1] = strCode[iIndex];
3732 strEncode[2] = strCode[ch - iIndex * 16];
3733 wsResultBuf << FX_WSTRC(strEncode);
3734 break;
3735 }
3736 ++i;
3737 }
dsinclaircf7f3222016-06-08 20:34:02 -07003738 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003739 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003740
Dan Sinclair1770c022016-03-14 14:14:16 -04003741 i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003742 iCount = FX_ArraySize(strReserved);
Dan Sinclair1770c022016-03-14 14:14:16 -04003743 while (i < iCount) {
3744 if (ch == strReserved[i]) {
3745 int32_t iIndex = ch / 16;
3746 strEncode[1] = strCode[iIndex];
3747 strEncode[2] = strCode[ch - iIndex * 16];
3748 wsResultBuf << FX_WSTRC(strEncode);
3749 break;
3750 }
3751 ++i;
3752 }
dsinclaircf7f3222016-06-08 20:34:02 -07003753 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003754 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003755
Dan Sinclair1770c022016-03-14 14:14:16 -04003756 i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003757 iCount = FX_ArraySize(strSpecial);
Dan Sinclair1770c022016-03-14 14:14:16 -04003758 while (i < iCount) {
3759 if (ch == strSpecial[i]) {
3760 wsResultBuf.AppendChar(ch);
3761 break;
3762 }
3763 ++i;
3764 }
dsinclaircf7f3222016-06-08 20:34:02 -07003765 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003766 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003767
3768 if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003769 int32_t iIndex = ch / 16;
3770 strEncode[1] = strCode[iIndex];
3771 strEncode[2] = strCode[ch - iIndex * 16];
3772 wsResultBuf << FX_WSTRC(strEncode);
3773 } else if (ch >= 0x20 && ch <= 0x7e) {
3774 wsResultBuf.AppendChar(ch);
3775 } else {
ochangf6be1452016-06-01 12:20:03 -07003776 const FX_WCHAR iRadix = 16;
Dan Sinclair1770c022016-03-14 14:14:16 -04003777 CFX_WideString strTmp;
3778 while (ch >= iRadix) {
3779 FX_WCHAR tmp = strCode[ch % iRadix];
3780 ch /= iRadix;
3781 strTmp += tmp;
3782 }
3783 strTmp += strCode[ch];
3784 int32_t iLen = strTmp.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07003785 if (iLen < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -04003786 break;
dsinclaircf7f3222016-06-08 20:34:02 -07003787
Dan Sinclair1770c022016-03-14 14:14:16 -04003788 int32_t iIndex = 0;
3789 if (iLen % 2 != 0) {
3790 strEncode[1] = '0';
3791 strEncode[2] = strTmp.GetAt(iLen - 1);
3792 iIndex = iLen - 2;
3793 } else {
3794 strEncode[1] = strTmp.GetAt(iLen - 1);
3795 strEncode[2] = strTmp.GetAt(iLen - 2);
3796 iIndex = iLen - 3;
3797 }
3798 wsResultBuf << FX_WSTRC(strEncode);
3799 while (iIndex > 0) {
3800 strEncode[1] = strTmp.GetAt(iIndex);
3801 strEncode[2] = strTmp.GetAt(iIndex - 1);
3802 iIndex -= 2;
3803 wsResultBuf << FX_WSTRC(strEncode);
3804 }
3805 }
3806 }
3807 wsResultBuf.AppendChar(0);
3808 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003809
tsepez28f97ff2016-04-04 16:41:35 -07003810 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003811 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003812}
dsinclair48d91dd2016-05-31 11:54:01 -07003813
3814// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003815void CXFA_FM2JSContext::EncodeHTML(const CFX_ByteStringC& szHTMLString,
3816 CFX_ByteTextBuf& szResultBuf) {
dsinclair179bebb2016-04-05 11:02:18 -07003817 CFX_ByteString str = szHTMLString.c_str();
tsepez4c3debb2016-04-08 12:20:38 -07003818 CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(str.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003819 const FX_WCHAR* strCode = L"0123456789abcdef";
3820 FX_WCHAR strEncode[9];
3821 strEncode[0] = '&';
3822 strEncode[1] = '#';
3823 strEncode[2] = 'x';
3824 strEncode[5] = ';';
3825 strEncode[6] = 0;
3826 strEncode[7] = ';';
3827 strEncode[8] = 0;
3828 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003829 int32_t iLen = wsHTMLString.GetLength();
3830 int32_t i = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003831 const FX_WCHAR* pData = wsHTMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003832 while (i < iLen) {
dsinclaircf7f3222016-06-08 20:34:02 -07003833 uint32_t ch = pData[i];
3834 CFX_WideString htmlReserve;
Dan Sinclair1770c022016-03-14 14:14:16 -04003835 if (HTMLCode2STR(ch, htmlReserve)) {
3836 wsResultBuf.AppendChar(L'&');
3837 wsResultBuf << htmlReserve;
3838 wsResultBuf.AppendChar(L';');
dsinclaircf7f3222016-06-08 20:34:02 -07003839 } else if (ch >= 32 && ch <= 126) {
3840 wsResultBuf.AppendChar((FX_WCHAR)ch);
3841 } else if (ch < 256) {
3842 int32_t iIndex = ch / 16;
3843 strEncode[3] = strCode[iIndex];
3844 strEncode[4] = strCode[ch - iIndex * 16];
3845 strEncode[5] = ';';
3846 strEncode[6] = 0;
3847 wsResultBuf << FX_WSTRC(strEncode);
Dan Sinclair1770c022016-03-14 14:14:16 -04003848 } else {
dsinclaircf7f3222016-06-08 20:34:02 -07003849 int32_t iBigByte = ch / 256;
3850 int32_t iLittleByte = ch % 256;
3851 strEncode[3] = strCode[iBigByte / 16];
3852 strEncode[4] = strCode[iBigByte % 16];
3853 strEncode[5] = strCode[iLittleByte / 16];
3854 strEncode[6] = strCode[iLittleByte % 16];
3855 wsResultBuf << FX_WSTRC(strEncode);
Dan Sinclair1770c022016-03-14 14:14:16 -04003856 }
3857 ++i;
3858 }
3859 wsResultBuf.AppendChar(0);
3860 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003861
tsepez28f97ff2016-04-04 16:41:35 -07003862 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003863 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003864}
dsinclair48d91dd2016-05-31 11:54:01 -07003865
3866// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003867void CXFA_FM2JSContext::EncodeXML(const CFX_ByteStringC& szXMLString,
3868 CFX_ByteTextBuf& szResultBuf) {
tsepez6fe7d212016-04-06 10:51:14 -07003869 CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003870 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003871 FX_WCHAR strEncode[9];
3872 strEncode[0] = '&';
3873 strEncode[1] = '#';
3874 strEncode[2] = 'x';
3875 strEncode[5] = ';';
3876 strEncode[6] = 0;
3877 strEncode[7] = ';';
3878 strEncode[8] = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04003879 const FX_WCHAR* strCode = L"0123456789abcdef";
tsepezbd9748d2016-04-13 21:40:19 -07003880 const FX_WCHAR* pData = wsXMLString.c_str();
dsinclaircf7f3222016-06-08 20:34:02 -07003881 for (int32_t u = 0; u < wsXMLString.GetLength(); ++u) {
3882 FX_WCHAR ch = pData[u];
Dan Sinclair1770c022016-03-14 14:14:16 -04003883 switch (ch) {
3884 case '"':
3885 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003886 wsResultBuf << CFX_WideStringC(L"quot");
Dan Sinclair1770c022016-03-14 14:14:16 -04003887 wsResultBuf.AppendChar(';');
3888 break;
3889 case '&':
3890 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003891 wsResultBuf << CFX_WideStringC(L"amp");
Dan Sinclair1770c022016-03-14 14:14:16 -04003892 wsResultBuf.AppendChar(';');
3893 break;
3894 case '\'':
3895 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003896 wsResultBuf << CFX_WideStringC(L"apos");
Dan Sinclair1770c022016-03-14 14:14:16 -04003897 wsResultBuf.AppendChar(';');
3898 break;
3899 case '<':
3900 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003901 wsResultBuf << CFX_WideStringC(L"lt");
Dan Sinclair1770c022016-03-14 14:14:16 -04003902 wsResultBuf.AppendChar(';');
3903 break;
3904 case '>':
3905 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003906 wsResultBuf << CFX_WideStringC(L"gt");
Dan Sinclair1770c022016-03-14 14:14:16 -04003907 wsResultBuf.AppendChar(';');
3908 break;
3909 default: {
3910 if (ch >= 32 && ch <= 126) {
3911 wsResultBuf.AppendChar(ch);
3912 } else if (ch < 256) {
dsinclaircf7f3222016-06-08 20:34:02 -07003913 int32_t iIndex = ch / 16;
Dan Sinclair1770c022016-03-14 14:14:16 -04003914 strEncode[3] = strCode[iIndex];
3915 strEncode[4] = strCode[ch - iIndex * 16];
3916 strEncode[5] = ';';
3917 strEncode[6] = 0;
3918 wsResultBuf << FX_WSTRC(strEncode);
3919 } else {
3920 int32_t iBigByte = ch / 256;
3921 int32_t iLittleByte = ch % 256;
3922 strEncode[3] = strCode[iBigByte / 16];
3923 strEncode[4] = strCode[iBigByte % 16];
3924 strEncode[5] = strCode[iLittleByte / 16];
3925 strEncode[6] = strCode[iLittleByte % 16];
3926 wsResultBuf << FX_WSTRC(strEncode);
3927 }
dsinclaircf7f3222016-06-08 20:34:02 -07003928 break;
3929 }
Dan Sinclair1770c022016-03-14 14:14:16 -04003930 }
3931 }
3932 wsResultBuf.AppendChar(0);
3933 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003934
tsepez28f97ff2016-04-04 16:41:35 -07003935 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003936 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003937}
dsinclair48d91dd2016-05-31 11:54:01 -07003938
3939// static
tsepezd19e9122016-11-02 15:43:18 -07003940bool CXFA_FM2JSContext::HTMLSTR2Code(const CFX_WideStringC& pData,
3941 uint32_t& iCode) {
tsepezb6853cf2016-04-25 11:23:43 -07003942 uint32_t uHash = FX_HashCode_GetW(pData, false);
3943 int32_t iStart = 0;
3944 int32_t iEnd = FX_ArraySize(reservesForDecode) - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003945 do {
tsepezb6853cf2016-04-25 11:23:43 -07003946 int32_t iMid = (iStart + iEnd) / 2;
3947 XFA_FMHtmlHashedReserveCode htmlhashedreservecode = reservesForDecode[iMid];
Dan Sinclair1770c022016-03-14 14:14:16 -04003948 if (uHash == htmlhashedreservecode.m_uHash) {
3949 iCode = htmlhashedreservecode.m_uCode;
tsepezd19e9122016-11-02 15:43:18 -07003950 return true;
tsepezb6853cf2016-04-25 11:23:43 -07003951 }
dsinclaircf7f3222016-06-08 20:34:02 -07003952
3953 if (uHash < htmlhashedreservecode.m_uHash)
Dan Sinclair1770c022016-03-14 14:14:16 -04003954 iEnd = iMid - 1;
dsinclaircf7f3222016-06-08 20:34:02 -07003955 else
Dan Sinclair1770c022016-03-14 14:14:16 -04003956 iStart = iMid + 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003957 } while (iStart <= iEnd);
tsepezd19e9122016-11-02 15:43:18 -07003958 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04003959}
dsinclair48d91dd2016-05-31 11:54:01 -07003960
3961// static
tsepezd19e9122016-11-02 15:43:18 -07003962bool CXFA_FM2JSContext::HTMLCode2STR(uint32_t iCode,
3963 CFX_WideString& wsHTMLReserve) {
dsinclaircf7f3222016-06-08 20:34:02 -07003964 int32_t iStart = 0;
3965 int32_t iEnd = FX_ArraySize(reservesForEncode) - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003966 do {
dsinclaircf7f3222016-06-08 20:34:02 -07003967 int32_t iMid = (iStart + iEnd) / 2;
3968 XFA_FMHtmlReserveCode htmlreservecode = reservesForEncode[iMid];
Dan Sinclair1770c022016-03-14 14:14:16 -04003969 if (iCode == htmlreservecode.m_uCode) {
3970 wsHTMLReserve = htmlreservecode.m_htmlReserve;
tsepezd19e9122016-11-02 15:43:18 -07003971 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04003972 }
dsinclaircf7f3222016-06-08 20:34:02 -07003973
3974 if (iCode < htmlreservecode.m_uCode)
3975 iEnd = iMid - 1;
3976 else
3977 iStart = iMid + 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003978 } while (iStart <= iEnd);
tsepezd19e9122016-11-02 15:43:18 -07003979 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04003980}
dsinclair48d91dd2016-05-31 11:54:01 -07003981
3982// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003983void CXFA_FM2JSContext::Format(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003984 const CFX_ByteStringC& szFuncName,
3985 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07003986 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclaircf7f3222016-06-08 20:34:02 -07003987 if (args.GetLength() < 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07003988 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Format");
dsinclaircf7f3222016-06-08 20:34:02 -07003989 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003990 }
dsinclaircf7f3222016-06-08 20:34:02 -07003991
3992 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3993 CFX_ByteString szPattern;
3994 ValueToUTF8String(argOne.get(), szPattern);
3995
3996 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3997 CFX_ByteString szValue;
3998 ValueToUTF8String(argTwo.get(), szValue);
3999
4000 CXFA_Document* pDoc = pContext->GetDocument();
4001 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
4002 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
4003 ASSERT(pThisNode);
4004
4005 CXFA_WidgetData widgetData(pThisNode);
4006 IFX_Locale* pLocale = widgetData.GetLocal();
4007 uint32_t patternType;
4008 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC());
4009 CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC());
4010 if (!PatternStringType(szPattern.AsStringC(), patternType)) {
4011 switch (patternType) {
4012 case XFA_VT_DATETIME: {
4013 FX_STRSIZE iTChar = wsPattern.Find(L'T');
4014 CFX_WideString wsDatePattern(L"date{");
4015 wsDatePattern += wsPattern.Left(iTChar) + L"} ";
4016
4017 CFX_WideString wsTimePattern(L"time{");
4018 wsTimePattern += wsPattern.Mid(iTChar + 1) + L"}";
4019 wsPattern = wsDatePattern + wsTimePattern;
4020 } break;
4021 case XFA_VT_DATE: {
4022 wsPattern = L"date{" + wsPattern + L"}";
4023 } break;
4024 case XFA_VT_TIME: {
4025 wsPattern = L"time{" + wsPattern + L"}";
4026 } break;
4027 case XFA_VT_TEXT: {
4028 wsPattern = L"text{" + wsPattern + L"}";
4029 } break;
4030 case XFA_VT_FLOAT: {
4031 wsPattern = L"num{" + wsPattern + L"}";
4032 } break;
4033 default: {
4034 CFX_WideString wsTestPattern;
4035 wsTestPattern = L"num{" + wsPattern + L"}";
4036 CXFA_LocaleValue tempLocaleValue(XFA_VT_FLOAT, wsValue, wsTestPattern,
4037 pLocale, pMgr);
4038 if (tempLocaleValue.IsValid()) {
4039 wsPattern = wsTestPattern;
4040 patternType = XFA_VT_FLOAT;
4041 } else {
4042 wsTestPattern = L"text{" + wsPattern + L"}";
4043 wsPattern = wsTestPattern;
4044 patternType = XFA_VT_TEXT;
4045 }
4046 } break;
4047 }
4048 }
4049 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, pMgr);
4050 CFX_WideString wsRet;
4051 if (!localeValue.FormatPatterns(wsRet, wsPattern, pLocale,
4052 XFA_VALUEPICTURE_Display)) {
4053 args.GetReturnValue()->SetString("");
4054 return;
4055 }
4056
4057 args.GetReturnValue()->SetString(
4058 FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004059}
dsinclair48d91dd2016-05-31 11:54:01 -07004060
4061// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004062void CXFA_FM2JSContext::Left(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004063 const CFX_ByteStringC& szFuncName,
4064 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004065 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004066 ToJSContext(pThis, nullptr)
4067 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Left");
dsinclaircf7f3222016-06-08 20:34:02 -07004068 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004069 }
dsinclaircf7f3222016-06-08 20:34:02 -07004070
4071 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4072 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4073 if ((ValueIsNull(pThis, argOne.get())) ||
4074 (ValueIsNull(pThis, argTwo.get()))) {
4075 args.GetReturnValue()->SetNull();
4076 return;
4077 }
4078
4079 CFX_ByteString sourceString;
4080 ValueToUTF8String(argOne.get(), sourceString);
4081 int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get()));
4082 args.GetReturnValue()->SetString(sourceString.Left(count).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004083}
dsinclair48d91dd2016-05-31 11:54:01 -07004084
4085// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004086void CXFA_FM2JSContext::Len(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004087 const CFX_ByteStringC& szFuncName,
4088 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004089 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004090 ToJSContext(pThis, nullptr)
4091 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Len");
dsinclaircf7f3222016-06-08 20:34:02 -07004092 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004093 }
dsinclaircf7f3222016-06-08 20:34:02 -07004094
4095 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4096 if (ValueIsNull(pThis, argOne.get())) {
4097 args.GetReturnValue()->SetNull();
4098 return;
4099 }
4100
4101 CFX_ByteString sourceString;
4102 ValueToUTF8String(argOne.get(), sourceString);
4103 args.GetReturnValue()->SetInteger(sourceString.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04004104}
dsinclair48d91dd2016-05-31 11:54:01 -07004105
4106// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004107void CXFA_FM2JSContext::Lower(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004108 const CFX_ByteStringC& szFuncName,
4109 CFXJSE_Arguments& args) {
4110 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004111 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004112 ToJSContext(pThis, nullptr)
4113 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Lower");
dsinclaircf7f3222016-06-08 20:34:02 -07004114 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004115 }
dsinclaircf7f3222016-06-08 20:34:02 -07004116
4117 CFX_ByteString argString;
4118 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4119 if (ValueIsNull(pThis, argOne.get())) {
4120 args.GetReturnValue()->SetNull();
4121 return;
4122 }
4123
4124 ValueToUTF8String(argOne.get(), argString);
4125 CFX_WideTextBuf lowStringBuf;
4126 CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC());
4127 const FX_WCHAR* pData = wsArgString.c_str();
4128 int32_t i = 0;
4129 while (i < argString.GetLength()) {
4130 int32_t ch = pData[i];
4131 if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE))
4132 ch += 32;
4133 else if (ch == 0x100 || ch == 0x102 || ch == 0x104)
4134 ch += 1;
4135
4136 lowStringBuf.AppendChar(ch);
4137 ++i;
4138 }
4139 lowStringBuf.AppendChar(0);
4140
4141 args.GetReturnValue()->SetString(
4142 FX_UTF8Encode(lowStringBuf.GetBuffer(), lowStringBuf.GetLength())
4143 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004144}
dsinclair48d91dd2016-05-31 11:54:01 -07004145
4146// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004147void CXFA_FM2JSContext::Ltrim(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004148 const CFX_ByteStringC& szFuncName,
4149 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004150 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004151 ToJSContext(pThis, nullptr)
4152 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ltrim");
dsinclaircf7f3222016-06-08 20:34:02 -07004153 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004154 }
dsinclaircf7f3222016-06-08 20:34:02 -07004155
4156 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4157 if (ValueIsNull(pThis, argOne.get())) {
4158 args.GetReturnValue()->SetNull();
4159 return;
4160 }
4161
4162 CFX_ByteString sourceString;
4163 ValueToUTF8String(argOne.get(), sourceString);
4164 sourceString.TrimLeft();
4165 args.GetReturnValue()->SetString(sourceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004166}
dsinclair48d91dd2016-05-31 11:54:01 -07004167
4168// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004169void CXFA_FM2JSContext::Parse(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004170 const CFX_ByteStringC& szFuncName,
4171 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004172 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclaircf7f3222016-06-08 20:34:02 -07004173 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07004174 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Parse");
dsinclaircf7f3222016-06-08 20:34:02 -07004175 return;
4176 }
4177
4178 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4179 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4180 if (ValueIsNull(pThis, argTwo.get())) {
4181 args.GetReturnValue()->SetNull();
4182 return;
4183 }
4184
4185 CFX_ByteString szPattern;
4186 ValueToUTF8String(argOne.get(), szPattern);
4187 CFX_ByteString szValue;
4188 ValueToUTF8String(argTwo.get(), szValue);
4189
4190 CXFA_Document* pDoc = pContext->GetDocument();
4191 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
4192 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
4193 ASSERT(pThisNode);
4194
4195 CXFA_WidgetData widgetData(pThisNode);
4196 IFX_Locale* pLocale = widgetData.GetLocal();
4197 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC());
4198 CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC());
4199 uint32_t patternType;
4200 if (PatternStringType(szPattern.AsStringC(), patternType)) {
4201 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4202 pMgr);
4203 if (!localeValue.IsValid()) {
4204 args.GetReturnValue()->SetString("");
4205 return;
4206 }
4207 args.GetReturnValue()->SetString(
4208 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4209 return;
4210 }
4211
4212 switch (patternType) {
4213 case XFA_VT_DATETIME: {
4214 FX_STRSIZE iTChar = wsPattern.Find(L'T');
4215 CFX_WideString wsDatePattern(L"date{" + wsPattern.Left(iTChar) + L"} ");
4216 CFX_WideString wsTimePattern(L"time{" + wsPattern.Mid(iTChar + 1) + L"}");
4217 wsPattern = wsDatePattern + wsTimePattern;
4218 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4219 pMgr);
4220 if (!localeValue.IsValid()) {
4221 args.GetReturnValue()->SetString("");
4222 return;
4223 }
4224 args.GetReturnValue()->SetString(
4225 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4226 return;
4227 }
4228 case XFA_VT_DATE: {
4229 wsPattern = L"date{" + wsPattern + L"}";
4230 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4231 pMgr);
4232 if (!localeValue.IsValid()) {
4233 args.GetReturnValue()->SetString("");
4234 return;
4235 }
4236 args.GetReturnValue()->SetString(
4237 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4238 return;
4239 }
4240 case XFA_VT_TIME: {
4241 wsPattern = L"time{" + wsPattern + L"}";
4242 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4243 pMgr);
4244 if (!localeValue.IsValid()) {
4245 args.GetReturnValue()->SetString("");
4246 return;
4247 }
4248 args.GetReturnValue()->SetString(
4249 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4250 return;
4251 }
4252 case XFA_VT_TEXT: {
4253 wsPattern = L"text{" + wsPattern + L"}";
4254 CXFA_LocaleValue localeValue(XFA_VT_TEXT, wsValue, wsPattern, pLocale,
4255 pMgr);
4256 if (!localeValue.IsValid()) {
4257 args.GetReturnValue()->SetString("");
4258 return;
4259 }
4260 args.GetReturnValue()->SetString(
4261 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4262 return;
4263 }
4264 case XFA_VT_FLOAT: {
4265 wsPattern = L"num{" + wsPattern + L"}";
4266 CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsPattern, pLocale,
4267 pMgr);
4268 if (!localeValue.IsValid()) {
4269 args.GetReturnValue()->SetString("");
4270 return;
4271 }
4272 args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum());
4273 return;
4274 }
4275 default: {
4276 CFX_WideString wsTestPattern;
4277 wsTestPattern = L"num{" + wsPattern + L"}";
4278 CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsTestPattern,
4279 pLocale, pMgr);
4280 if (localeValue.IsValid()) {
4281 args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum());
4282 return;
4283 }
4284
4285 wsTestPattern = L"text{" + wsPattern + L"}";
4286 CXFA_LocaleValue localeValue2(XFA_VT_TEXT, wsValue, wsTestPattern,
4287 pLocale, pMgr);
4288 if (!localeValue2.IsValid()) {
4289 args.GetReturnValue()->SetString("");
4290 return;
4291 }
4292 args.GetReturnValue()->SetString(
4293 FX_UTF8Encode(localeValue2.GetValue()).AsStringC());
4294 return;
4295 }
Dan Sinclair1770c022016-03-14 14:14:16 -04004296 }
4297}
dsinclair48d91dd2016-05-31 11:54:01 -07004298
4299// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004300void CXFA_FM2JSContext::Replace(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004301 const CFX_ByteStringC& szFuncName,
4302 CFXJSE_Arguments& args) {
4303 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004304 if (argc < 2 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004305 ToJSContext(pThis, nullptr)
4306 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Replace");
dsinclaircf7f3222016-06-08 20:34:02 -07004307 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004308 }
dsinclaircf7f3222016-06-08 20:34:02 -07004309
4310 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4311 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4312 CFX_ByteString oneString;
4313 CFX_ByteString twoString;
4314 if (!ValueIsNull(pThis, argOne.get()) && !ValueIsNull(pThis, argTwo.get())) {
4315 ValueToUTF8String(argOne.get(), oneString);
4316 ValueToUTF8String(argTwo.get(), twoString);
4317 }
4318
4319 CFX_ByteString threeString;
4320 if (argc > 2) {
4321 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
4322 ValueToUTF8String(argThree.get(), threeString);
4323 }
4324
4325 int32_t iFindLen = twoString.GetLength();
4326 CFX_ByteTextBuf resultString;
4327 int32_t iFindIndex = 0;
4328 for (int32_t u = 0; u < oneString.GetLength(); ++u) {
4329 uint8_t ch = oneString.GetAt(u);
4330 if (ch != twoString.GetAt(iFindIndex)) {
4331 resultString.AppendChar(ch);
4332 continue;
4333 }
4334
4335 int32_t iTemp = u + 1;
4336 ++iFindIndex;
4337 while (iFindIndex < iFindLen) {
4338 uint8_t chTemp = oneString.GetAt(iTemp);
4339 if (chTemp != twoString.GetAt(iFindIndex)) {
4340 iFindIndex = 0;
4341 break;
4342 }
4343
4344 ++iTemp;
4345 ++iFindIndex;
4346 }
4347 if (iFindIndex == iFindLen) {
4348 resultString << threeString.AsStringC();
4349 u += iFindLen - 1;
4350 iFindIndex = 0;
4351 } else {
4352 resultString.AppendChar(ch);
4353 }
4354 }
4355 resultString.AppendChar(0);
4356 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004357}
dsinclair48d91dd2016-05-31 11:54:01 -07004358
4359// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004360void CXFA_FM2JSContext::Right(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004361 const CFX_ByteStringC& szFuncName,
4362 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004363 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004364 ToJSContext(pThis, nullptr)
4365 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Right");
dsinclaircf7f3222016-06-08 20:34:02 -07004366 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004367 }
dsinclaircf7f3222016-06-08 20:34:02 -07004368
4369 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4370 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4371 if ((ValueIsNull(pThis, argOne.get())) ||
4372 (ValueIsNull(pThis, argTwo.get()))) {
4373 args.GetReturnValue()->SetNull();
4374 return;
4375 }
4376
4377 CFX_ByteString sourceString;
4378 ValueToUTF8String(argOne.get(), sourceString);
4379 int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get()));
4380 args.GetReturnValue()->SetString(sourceString.Right(count).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004381}
dsinclair48d91dd2016-05-31 11:54:01 -07004382
4383// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004384void CXFA_FM2JSContext::Rtrim(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004385 const CFX_ByteStringC& szFuncName,
4386 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004387 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004388 ToJSContext(pThis, nullptr)
4389 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Rtrim");
dsinclaircf7f3222016-06-08 20:34:02 -07004390 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004391 }
dsinclaircf7f3222016-06-08 20:34:02 -07004392
4393 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4394 if (ValueIsNull(pThis, argOne.get())) {
4395 args.GetReturnValue()->SetNull();
4396 return;
4397 }
4398
4399 CFX_ByteString sourceString;
4400 ValueToUTF8String(argOne.get(), sourceString);
4401 sourceString.TrimRight();
4402 args.GetReturnValue()->SetString(sourceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004403}
dsinclair48d91dd2016-05-31 11:54:01 -07004404
4405// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004406void CXFA_FM2JSContext::Space(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004407 const CFX_ByteStringC& szFuncName,
4408 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004409 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004410 ToJSContext(pThis, nullptr)
4411 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Space");
dsinclaircf7f3222016-06-08 20:34:02 -07004412 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004413 }
dsinclaircf7f3222016-06-08 20:34:02 -07004414
4415 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4416 if (argOne->IsNull()) {
4417 args.GetReturnValue()->SetNull();
4418 return;
4419 }
4420
4421 int32_t count = std::max(0, ValueToInteger(pThis, argOne.get()));
4422 CFX_ByteTextBuf spaceString;
4423 int32_t index = 0;
4424 while (index < count) {
4425 spaceString.AppendByte(' ');
4426 index++;
4427 }
4428 spaceString.AppendByte(0);
4429 args.GetReturnValue()->SetString(spaceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004430}
dsinclair48d91dd2016-05-31 11:54:01 -07004431
4432// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004433void CXFA_FM2JSContext::Str(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004434 const CFX_ByteStringC& szFuncName,
4435 CFXJSE_Arguments& args) {
4436 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004437 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004438 ToJSContext(pThis, nullptr)
4439 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Str");
dsinclaircf7f3222016-06-08 20:34:02 -07004440 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004441 }
dsinclaircf7f3222016-06-08 20:34:02 -07004442
4443 std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0);
4444 if (numberValue->IsNull()) {
4445 args.GetReturnValue()->SetNull();
4446 return;
4447 }
4448 FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get());
4449
4450 int32_t iWidth = 10;
4451 if (argc > 1) {
4452 std::unique_ptr<CFXJSE_Value> widthValue = GetSimpleValue(pThis, args, 1);
4453 iWidth = static_cast<int32_t>(ValueToFloat(pThis, widthValue.get()));
4454 }
4455
4456 int32_t iPrecision = 0;
4457 if (argc > 2) {
4458 std::unique_ptr<CFXJSE_Value> precisionValue =
4459 GetSimpleValue(pThis, args, 2);
4460 iPrecision = std::max(
4461 0, static_cast<int32_t>(ValueToFloat(pThis, precisionValue.get())));
4462 }
4463
4464 CFX_ByteString numberString;
4465 CFX_ByteString formatStr = "%";
4466 if (iPrecision) {
4467 formatStr += ".";
4468 formatStr += CFX_ByteString::FormatInteger(iPrecision);
4469 }
4470 formatStr += "f";
4471 numberString.Format(formatStr.c_str(), fNumber);
4472
4473 const FX_CHAR* pData = numberString.c_str();
4474 int32_t iLength = numberString.GetLength();
4475 int32_t u = 0;
4476 while (u < iLength) {
4477 if (pData[u] == '.')
4478 break;
4479
4480 ++u;
4481 }
4482
4483 CFX_ByteTextBuf resultBuf;
4484 if (u > iWidth || (iPrecision + u) >= iWidth) {
4485 int32_t i = 0;
4486 while (i < iWidth) {
4487 resultBuf.AppendChar('*');
4488 ++i;
4489 }
4490 resultBuf.AppendChar(0);
4491 args.GetReturnValue()->SetString(resultBuf.AsStringC());
4492 return;
4493 }
4494
4495 if (u == iLength) {
4496 if (iLength > iWidth) {
4497 int32_t i = 0;
4498 while (i < iWidth) {
4499 resultBuf.AppendChar('*');
4500 ++i;
4501 }
4502 } else {
4503 int32_t i = 0;
4504 while (i < iWidth - iLength) {
4505 resultBuf.AppendChar(' ');
4506 ++i;
4507 }
4508 resultBuf << pData;
4509 }
4510 args.GetReturnValue()->SetString(resultBuf.AsStringC());
4511 return;
4512 }
4513
4514 int32_t iLeavingSpace = iWidth - u - iPrecision;
4515 if (iPrecision != 0)
4516 iLeavingSpace--;
4517
4518 int32_t i = 0;
4519 while (i < iLeavingSpace) {
4520 resultBuf.AppendChar(' ');
4521 ++i;
4522 }
4523 i = 0;
4524 while (i < u) {
4525 resultBuf.AppendChar(pData[i]);
4526 ++i;
4527 }
4528 if (iPrecision != 0)
4529 resultBuf.AppendChar('.');
4530
4531 u++;
4532 i = 0;
4533 while (u < iLength) {
4534 if (i >= iPrecision)
4535 break;
4536
4537 resultBuf.AppendChar(pData[u]);
4538 ++i;
4539 ++u;
4540 }
4541 while (i < iPrecision) {
4542 resultBuf.AppendChar('0');
4543 ++i;
4544 }
4545 resultBuf.AppendChar(0);
4546 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004547}
dsinclair48d91dd2016-05-31 11:54:01 -07004548
4549// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004550void CXFA_FM2JSContext::Stuff(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004551 const CFX_ByteStringC& szFuncName,
4552 CFXJSE_Arguments& args) {
4553 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004554 if (argc < 3 || argc > 4) {
dsinclair8f3074b2016-06-02 17:45:25 -07004555 ToJSContext(pThis, nullptr)
4556 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Stuff");
dsinclaircf7f3222016-06-08 20:34:02 -07004557 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004558 }
dsinclaircf7f3222016-06-08 20:34:02 -07004559
4560 CFX_ByteString sourceString;
4561 CFX_ByteString insertString;
4562 int32_t iLength = 0;
4563 int32_t iStart = 0;
4564 int32_t iDelete = 0;
4565 std::unique_ptr<CFXJSE_Value> sourceValue = GetSimpleValue(pThis, args, 0);
4566 std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1);
4567 std::unique_ptr<CFXJSE_Value> deleteValue = GetSimpleValue(pThis, args, 2);
4568 if (!sourceValue->IsNull() && !startValue->IsNull() &&
4569 !deleteValue->IsNull()) {
4570 ValueToUTF8String(sourceValue.get(), sourceString);
4571 iLength = sourceString.GetLength();
4572 iStart = std::min(iLength, std::max(1, static_cast<int32_t>(ValueToFloat(
4573 pThis, startValue.get()))));
4574 iDelete = std::max(
4575 0, static_cast<int32_t>(ValueToFloat(pThis, deleteValue.get())));
4576 }
4577
4578 if (argc > 3) {
4579 std::unique_ptr<CFXJSE_Value> insertValue = GetSimpleValue(pThis, args, 3);
4580 ValueToUTF8String(insertValue.get(), insertString);
4581 }
4582
4583 iStart -= 1;
4584 CFX_ByteTextBuf resultString;
4585 int32_t i = 0;
4586 while (i < iStart) {
4587 resultString.AppendChar(sourceString.GetAt(i));
4588 ++i;
4589 }
4590 resultString << insertString.AsStringC();
4591 i = iStart + iDelete;
4592 while (i < iLength) {
4593 resultString.AppendChar(sourceString.GetAt(i));
4594 ++i;
4595 }
4596 resultString.AppendChar(0);
4597 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004598}
dsinclair48d91dd2016-05-31 11:54:01 -07004599
4600// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004601void CXFA_FM2JSContext::Substr(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004602 const CFX_ByteStringC& szFuncName,
4603 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004604 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004605 ToJSContext(pThis, nullptr)
4606 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Substr");
dsinclaircf7f3222016-06-08 20:34:02 -07004607 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004608 }
dsinclaircf7f3222016-06-08 20:34:02 -07004609
4610 std::unique_ptr<CFXJSE_Value> stringValue = GetSimpleValue(pThis, args, 0);
4611 std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1);
4612 std::unique_ptr<CFXJSE_Value> endValue = GetSimpleValue(pThis, args, 2);
4613 if (ValueIsNull(pThis, stringValue.get()) ||
4614 (ValueIsNull(pThis, startValue.get())) ||
4615 (ValueIsNull(pThis, endValue.get()))) {
4616 args.GetReturnValue()->SetNull();
4617 return;
4618 }
4619
4620 CFX_ByteString szSourceStr;
4621 int32_t iStart = 0;
4622 int32_t iCount = 0;
4623 ValueToUTF8String(stringValue.get(), szSourceStr);
4624 int32_t iLength = szSourceStr.GetLength();
4625 if (iLength == 0) {
4626 args.GetReturnValue()->SetString("");
4627 return;
4628 }
4629
4630 iStart = std::min(
4631 iLength,
4632 std::max(1, static_cast<int32_t>(ValueToFloat(pThis, startValue.get()))));
4633 iCount =
4634 std::max(0, static_cast<int32_t>(ValueToFloat(pThis, endValue.get())));
4635
4636 iStart -= 1;
4637 args.GetReturnValue()->SetString(szSourceStr.Mid(iStart, iCount).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004638}
dsinclair48d91dd2016-05-31 11:54:01 -07004639
4640// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004641void CXFA_FM2JSContext::Uuid(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004642 const CFX_ByteStringC& szFuncName,
4643 CFXJSE_Arguments& args) {
4644 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004645 if (argc < 0 || argc > 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004646 ToJSContext(pThis, nullptr)
4647 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Uuid");
dsinclaircf7f3222016-06-08 20:34:02 -07004648 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004649 }
dsinclaircf7f3222016-06-08 20:34:02 -07004650
4651 int32_t iNum = 0;
4652 if (argc > 0) {
4653 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4654 iNum = static_cast<int32_t>(ValueToFloat(pThis, argOne.get()));
4655 }
4656 FX_GUID guid;
4657 FX_GUID_CreateV4(&guid);
4658
4659 CFX_ByteString bsUId;
tsepez478ed622016-10-27 14:32:33 -07004660 FX_GUID_ToString(&guid, bsUId, !!iNum);
dsinclaircf7f3222016-06-08 20:34:02 -07004661 args.GetReturnValue()->SetString(bsUId.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004662}
dsinclair48d91dd2016-05-31 11:54:01 -07004663
4664// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004665void CXFA_FM2JSContext::Upper(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004666 const CFX_ByteStringC& szFuncName,
4667 CFXJSE_Arguments& args) {
4668 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004669 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004670 ToJSContext(pThis, nullptr)
4671 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Upper");
dsinclaircf7f3222016-06-08 20:34:02 -07004672 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004673 }
dsinclaircf7f3222016-06-08 20:34:02 -07004674
4675 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4676 if (ValueIsNull(pThis, argOne.get())) {
4677 args.GetReturnValue()->SetNull();
4678 return;
4679 }
4680
4681 CFX_ByteString argString;
4682 ValueToUTF8String(argOne.get(), argString);
4683
4684 CFX_WideTextBuf upperStringBuf;
4685 CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC());
4686 const FX_WCHAR* pData = wsArgString.c_str();
4687 int32_t i = 0;
4688 while (i < wsArgString.GetLength()) {
4689 int32_t ch = pData[i];
4690 if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE))
4691 ch -= 32;
4692 else if (ch == 0x101 || ch == 0x103 || ch == 0x105)
4693 ch -= 1;
4694
4695 upperStringBuf.AppendChar(ch);
4696 ++i;
4697 }
4698 upperStringBuf.AppendChar(0);
4699
4700 args.GetReturnValue()->SetString(
4701 FX_UTF8Encode(upperStringBuf.GetBuffer(), upperStringBuf.GetLength())
4702 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004703}
dsinclair48d91dd2016-05-31 11:54:01 -07004704
4705// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004706void CXFA_FM2JSContext::WordNum(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004707 const CFX_ByteStringC& szFuncName,
4708 CFXJSE_Arguments& args) {
4709 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004710 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004711 ToJSContext(pThis, nullptr)
4712 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"WordNum");
dsinclaircf7f3222016-06-08 20:34:02 -07004713 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004714 }
dsinclaircf7f3222016-06-08 20:34:02 -07004715
4716 std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0);
4717 if (numberValue->IsNull()) {
4718 args.GetReturnValue()->SetNull();
4719 return;
4720 }
4721 FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get());
4722
4723 int32_t iIdentifier = 0;
4724 if (argc > 1) {
4725 std::unique_ptr<CFXJSE_Value> identifierValue =
4726 GetSimpleValue(pThis, args, 1);
4727 if (identifierValue->IsNull()) {
4728 args.GetReturnValue()->SetNull();
4729 return;
4730 }
4731 iIdentifier =
4732 static_cast<int32_t>(ValueToFloat(pThis, identifierValue.get()));
4733 }
4734
4735 CFX_ByteString localeString;
4736 if (argc > 2) {
4737 std::unique_ptr<CFXJSE_Value> localeValue = GetSimpleValue(pThis, args, 2);
4738 if (localeValue->IsNull()) {
4739 args.GetReturnValue()->SetNull();
4740 return;
4741 }
4742 ValueToUTF8String(localeValue.get(), localeString);
4743 }
4744
4745 if (fNumber < 0.0f || fNumber > 922337203685477550.0f) {
4746 args.GetReturnValue()->SetString("*");
4747 return;
4748 }
4749
4750 CFX_ByteString numberString;
4751 numberString.Format("%.2f", fNumber);
4752
4753 CFX_ByteTextBuf resultBuf;
4754 WordUS(numberString.AsStringC(), iIdentifier, resultBuf);
4755 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004756}
dsinclair48d91dd2016-05-31 11:54:01 -07004757
4758// static
Dan Sinclair1770c022016-03-14 14:14:16 -04004759void CXFA_FM2JSContext::TrillionUS(const CFX_ByteStringC& szData,
4760 CFX_ByteTextBuf& strBuf) {
4761 CFX_ByteStringC pUnits[] = {"zero", "one", "two", "three", "four",
4762 "five", "six", "seven", "eight", "nine"};
4763 CFX_ByteStringC pCapUnits[] = {"Zero", "One", "Two", "Three", "Four",
4764 "Five", "Six", "Seven", "Eight", "Nine"};
4765 CFX_ByteStringC pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen",
4766 "Fourteen", "Fifteen", "Sixteen", "Seventeen",
4767 "Eighteen", "Nineteen"};
4768 CFX_ByteStringC pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty",
4769 "Sixty", "Seventy", "Eighty", "Ninety"};
4770 CFX_ByteStringC pComm[] = {" Hundred ", " Thousand ", " Million ",
4771 " Billion ", "Trillion"};
dsinclair179bebb2016-04-05 11:02:18 -07004772 const FX_CHAR* pData = szData.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04004773 int32_t iLength = szData.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004774 int32_t iComm = 0;
4775 if (iLength > 12)
Dan Sinclair1770c022016-03-14 14:14:16 -04004776 iComm = 4;
dsinclair947c8732016-06-08 20:40:30 -07004777 else if (iLength > 9)
Dan Sinclair1770c022016-03-14 14:14:16 -04004778 iComm = 3;
dsinclair947c8732016-06-08 20:40:30 -07004779 else if (iLength > 6)
Dan Sinclair1770c022016-03-14 14:14:16 -04004780 iComm = 2;
dsinclair947c8732016-06-08 20:40:30 -07004781 else if (iLength > 3)
Dan Sinclair1770c022016-03-14 14:14:16 -04004782 iComm = 1;
dsinclair947c8732016-06-08 20:40:30 -07004783
Dan Sinclair1770c022016-03-14 14:14:16 -04004784 int32_t iFirstCount = iLength % 3;
dsinclair947c8732016-06-08 20:40:30 -07004785 if (iFirstCount == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04004786 iFirstCount = 3;
dsinclair947c8732016-06-08 20:40:30 -07004787
4788 int32_t iIndex = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04004789 if (iFirstCount == 3) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004790 if (pData[iIndex] != '0') {
4791 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004792 strBuf << pComm[0];
4793 }
dsinclair2b6d64e2016-06-06 11:39:42 -07004794 if (pData[iIndex + 1] == '0') {
4795 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004796 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004797 if (pData[iIndex + 1] > '1') {
4798 strBuf << pLastTens[pData[iIndex + 1] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004799 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004800 strBuf << pUnits[pData[iIndex + 2] - '0'];
4801 } else if (pData[iIndex + 1] == '1') {
4802 strBuf << pTens[pData[iIndex + 2] - '0'];
4803 } else if (pData[iIndex + 1] == '0') {
4804 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004805 }
4806 }
4807 iIndex += 3;
4808 } else if (iFirstCount == 2) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004809 if (pData[iIndex] == '0') {
4810 strBuf << pCapUnits[pData[iIndex + 1] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004811 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004812 if (pData[iIndex] > '1') {
4813 strBuf << pLastTens[pData[iIndex] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004814 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004815 strBuf << pUnits[pData[iIndex + 1] - '0'];
4816 } else if (pData[iIndex] == '1') {
4817 strBuf << pTens[pData[iIndex + 1] - '0'];
4818 } else if (pData[iIndex] == '0') {
4819 strBuf << pCapUnits[pData[iIndex + 1] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004820 }
4821 }
4822 iIndex += 2;
4823 } else if (iFirstCount == 1) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004824 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004825 iIndex += 1;
4826 }
4827 if (iLength > 3 && iFirstCount > 0) {
4828 strBuf << pComm[iComm];
4829 --iComm;
4830 }
4831 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004832 if (pData[iIndex] != '0') {
4833 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004834 strBuf << pComm[0];
4835 }
dsinclair2b6d64e2016-06-06 11:39:42 -07004836 if (pData[iIndex + 1] == '0') {
4837 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004838 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004839 if (pData[iIndex + 1] > '1') {
4840 strBuf << pLastTens[pData[iIndex + 1] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004841 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004842 strBuf << pUnits[pData[iIndex + 2] - '0'];
4843 } else if (pData[iIndex + 1] == '1') {
4844 strBuf << pTens[pData[iIndex + 2] - '0'];
4845 } else if (pData[iIndex + 1] == '0') {
4846 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004847 }
4848 }
4849 if (iIndex < iLength - 3) {
4850 strBuf << pComm[iComm];
4851 --iComm;
4852 }
4853 iIndex += 3;
4854 }
4855}
dsinclair48d91dd2016-05-31 11:54:01 -07004856
4857// static
Dan Sinclair1770c022016-03-14 14:14:16 -04004858void CXFA_FM2JSContext::WordUS(const CFX_ByteStringC& szData,
4859 int32_t iStyle,
4860 CFX_ByteTextBuf& strBuf) {
dsinclair179bebb2016-04-05 11:02:18 -07004861 const FX_CHAR* pData = szData.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04004862 int32_t iLength = szData.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004863 if (iStyle < 0 || iStyle > 2) {
4864 return;
4865 }
4866
4867 int32_t iIndex = 0;
4868 while (iIndex < iLength) {
4869 if (pData[iIndex] == '.')
Dan Sinclair1770c022016-03-14 14:14:16 -04004870 break;
dsinclair947c8732016-06-08 20:40:30 -07004871 ++iIndex;
4872 }
4873 int32_t iInteger = iIndex;
4874 iIndex = 0;
4875 while (iIndex < iInteger) {
4876 int32_t iCount = (iInteger - iIndex) % 12;
4877 if (!iCount && iInteger - iIndex > 0)
4878 iCount = 12;
4879
4880 TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf);
4881 iIndex += iCount;
4882 if (iIndex < iInteger)
4883 strBuf << " Trillion ";
4884 }
4885
4886 if (iStyle > 0)
4887 strBuf << " Dollars";
4888
4889 if (iStyle > 1 && iInteger < iLength) {
4890 strBuf << " And ";
4891 iIndex = iInteger + 1;
4892 while (iIndex < iLength) {
4893 int32_t iCount = (iLength - iIndex) % 12;
4894 if (!iCount && iLength - iIndex > 0)
4895 iCount = 12;
4896
4897 TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf);
4898 iIndex += iCount;
4899 if (iIndex < iLength)
4900 strBuf << " Trillion ";
4901 }
4902 strBuf << " Cents";
Dan Sinclair1770c022016-03-14 14:14:16 -04004903 }
4904}
dsinclair48d91dd2016-05-31 11:54:01 -07004905
4906// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004907void CXFA_FM2JSContext::Get(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004908 const CFX_ByteStringC& szFuncName,
4909 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004910 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07004911 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07004912 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Get");
dsinclair947c8732016-06-08 20:40:30 -07004913 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004914 }
dsinclair947c8732016-06-08 20:40:30 -07004915
4916 CXFA_Document* pDoc = pContext->GetDocument();
4917 if (!pDoc)
4918 return;
4919
dsinclaira1b07722016-07-11 08:20:58 -07004920 IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider();
dsinclair947c8732016-06-08 20:40:30 -07004921 if (!pAppProvider)
4922 return;
4923
4924 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4925 CFX_ByteString urlString;
4926 ValueToUTF8String(argOne.get(), urlString);
tsepezad2441e2016-10-24 10:19:11 -07004927 IFX_SeekableReadStream* pFile = pAppProvider->DownloadURL(
dsinclair947c8732016-06-08 20:40:30 -07004928 CFX_WideString::FromUTF8(urlString.AsStringC()));
4929 if (!pFile)
4930 return;
4931
4932 int32_t size = pFile->GetSize();
4933 std::unique_ptr<uint8_t> pData(FX_Alloc(uint8_t, size));
4934 pFile->ReadBlock(pData.get(), size);
4935 args.GetReturnValue()->SetString(CFX_ByteStringC(pData.get(), size));
4936 pFile->Release();
Dan Sinclair1770c022016-03-14 14:14:16 -04004937}
dsinclair48d91dd2016-05-31 11:54:01 -07004938
4939// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004940void CXFA_FM2JSContext::Post(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004941 const CFX_ByteStringC& szFuncName,
4942 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004943 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04004944 int32_t argc = args.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004945 if (argc < 2 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07004946 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Post");
dsinclair947c8732016-06-08 20:40:30 -07004947 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004948 }
dsinclair947c8732016-06-08 20:40:30 -07004949
4950 CXFA_Document* pDoc = pContext->GetDocument();
4951 if (!pDoc)
4952 return;
4953
dsinclaira1b07722016-07-11 08:20:58 -07004954 IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider();
dsinclair947c8732016-06-08 20:40:30 -07004955 if (!pAppProvider)
4956 return;
4957
4958 CFX_ByteString bsURL;
4959 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4960 ValueToUTF8String(argOne.get(), bsURL);
4961
4962 CFX_ByteString bsData;
4963 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4964 ValueToUTF8String(argTwo.get(), bsData);
4965
4966 CFX_ByteString bsContentType;
4967 if (argc > 2) {
4968 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
4969 ValueToUTF8String(argThree.get(), bsContentType);
4970 }
4971
4972 CFX_ByteString bsEncode;
4973 if (argc > 3) {
4974 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
4975 ValueToUTF8String(argFour.get(), bsEncode);
4976 }
4977
4978 CFX_ByteString bsHeader;
4979 if (argc > 4) {
4980 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
4981 ValueToUTF8String(argFive.get(), bsHeader);
4982 }
4983
4984 CFX_WideString decodedResponse;
4985 if (!pAppProvider->PostRequestURL(
4986 CFX_WideString::FromUTF8(bsURL.AsStringC()),
4987 CFX_WideString::FromUTF8(bsData.AsStringC()),
4988 CFX_WideString::FromUTF8(bsContentType.AsStringC()),
4989 CFX_WideString::FromUTF8(bsEncode.AsStringC()),
4990 CFX_WideString::FromUTF8(bsHeader.AsStringC()), decodedResponse)) {
4991 pContext->ThrowException(XFA_IDS_SERVER_DENY);
4992 return;
4993 }
4994
4995 args.GetReturnValue()->SetString(
4996 FX_UTF8Encode(decodedResponse.c_str(), decodedResponse.GetLength())
4997 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004998}
dsinclair48d91dd2016-05-31 11:54:01 -07004999
5000// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005001void CXFA_FM2JSContext::Put(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005002 const CFX_ByteStringC& szFuncName,
5003 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005004 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04005005 int32_t argc = args.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07005006 if (argc < 2 || argc > 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07005007 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Put");
dsinclair947c8732016-06-08 20:40:30 -07005008 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005009 }
dsinclair947c8732016-06-08 20:40:30 -07005010
5011 CXFA_Document* pDoc = pContext->GetDocument();
5012 if (!pDoc)
5013 return;
5014
dsinclaira1b07722016-07-11 08:20:58 -07005015 IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider();
dsinclair947c8732016-06-08 20:40:30 -07005016 if (!pAppProvider)
5017 return;
5018
5019 CFX_ByteString bsURL;
5020 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5021 ValueToUTF8String(argOne.get(), bsURL);
5022
5023 CFX_ByteString bsData;
5024 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
5025 ValueToUTF8String(argTwo.get(), bsData);
5026
5027 CFX_ByteString bsEncode;
5028 if (argc > 2) {
5029 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
5030 ValueToUTF8String(argThree.get(), bsEncode);
5031 }
5032
5033 if (!pAppProvider->PutRequestURL(
5034 CFX_WideString::FromUTF8(bsURL.AsStringC()),
5035 CFX_WideString::FromUTF8(bsData.AsStringC()),
5036 CFX_WideString::FromUTF8(bsEncode.AsStringC()))) {
5037 pContext->ThrowException(XFA_IDS_SERVER_DENY);
5038 return;
5039 }
5040
5041 args.GetReturnValue()->SetString("");
Dan Sinclair1770c022016-03-14 14:14:16 -04005042}
dsinclair48d91dd2016-05-31 11:54:01 -07005043
5044// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005045void CXFA_FM2JSContext::assign_value_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005046 const CFX_ByteStringC& szFuncName,
5047 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005048 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07005049 if (args.GetLength() != 2) {
5050 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5051 return;
5052 }
5053
5054 std::unique_ptr<CFXJSE_Value> lValue = args.GetValue(0);
5055 std::unique_ptr<CFXJSE_Value> rValue = GetSimpleValue(pThis, args, 1);
5056 if (lValue->IsArray()) {
5057 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5058 std::unique_ptr<CFXJSE_Value> leftLengthValue(new CFXJSE_Value(pIsolate));
5059 lValue->GetObjectProperty("length", leftLengthValue.get());
5060 int32_t iLeftLength = leftLengthValue->ToInteger();
5061 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
5062 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
5063 lValue->GetObjectPropertyByIdx(1, propertyValue.get());
5064 if (propertyValue->IsNull()) {
5065 for (int32_t i = 2; i < iLeftLength; i++) {
5066 lValue->GetObjectPropertyByIdx(i, jsObjectValue.get());
5067 if (!SetObjectDefaultValue(jsObjectValue.get(), rValue.get())) {
5068 pContext->ThrowException(XFA_IDS_NOT_DEFAUL_VALUE);
5069 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005070 }
5071 }
dsinclair947c8732016-06-08 20:40:30 -07005072 } else {
dsinclair947c8732016-06-08 20:40:30 -07005073 for (int32_t i = 2; i < iLeftLength; i++) {
5074 lValue->GetObjectPropertyByIdx(i, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -07005075 jsObjectValue->SetObjectProperty(propertyValue->ToString().AsStringC(),
5076 rValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005077 }
5078 }
dsinclair947c8732016-06-08 20:40:30 -07005079 } else if (lValue->IsObject()) {
5080 if (!SetObjectDefaultValue(lValue.get(), rValue.get())) {
5081 pContext->ThrowException(XFA_IDS_NOT_DEFAUL_VALUE);
5082 return;
5083 }
Dan Sinclair1770c022016-03-14 14:14:16 -04005084 }
dsinclair947c8732016-06-08 20:40:30 -07005085 args.GetReturnValue()->Assign(rValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005086}
dsinclair48d91dd2016-05-31 11:54:01 -07005087
5088// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005089void CXFA_FM2JSContext::logical_or_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005090 const CFX_ByteStringC& szFuncName,
5091 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005092 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005093 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005094 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005095 }
dsinclair947c8732016-06-08 20:40:30 -07005096
5097 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5098 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5099 if (argFirst->IsNull() && argSecond->IsNull()) {
5100 args.GetReturnValue()->SetNull();
5101 return;
5102 }
5103
5104 FX_FLOAT first = ValueToFloat(pThis, argFirst.get());
5105 FX_FLOAT second = ValueToFloat(pThis, argSecond.get());
5106 args.GetReturnValue()->SetInteger((first || second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005107}
dsinclair48d91dd2016-05-31 11:54:01 -07005108
5109// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005110void CXFA_FM2JSContext::logical_and_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005111 const CFX_ByteStringC& szFuncName,
5112 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005113 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005114 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005115 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005116 }
dsinclair947c8732016-06-08 20:40:30 -07005117
5118 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5119 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5120 if (argFirst->IsNull() && argSecond->IsNull()) {
5121 args.GetReturnValue()->SetNull();
5122 return;
5123 }
5124
5125 FX_FLOAT first = ValueToFloat(pThis, argFirst.get());
5126 FX_FLOAT second = ValueToFloat(pThis, argSecond.get());
5127 args.GetReturnValue()->SetInteger((first && second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005128}
dsinclair48d91dd2016-05-31 11:54:01 -07005129
5130// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005131void CXFA_FM2JSContext::equality_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005132 const CFX_ByteStringC& szFuncName,
5133 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005134 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005135 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005136 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005137 }
dsinclair947c8732016-06-08 20:40:30 -07005138
5139 if (fm_ref_equal(pThis, args)) {
5140 args.GetReturnValue()->SetInteger(1);
5141 return;
5142 }
5143
5144 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5145 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5146 if (argFirst->IsNull() || argSecond->IsNull()) {
5147 args.GetReturnValue()->SetInteger(
5148 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5149 return;
5150 }
5151
5152 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair2f5582f2016-06-09 11:48:23 -07005153 args.GetReturnValue()->SetInteger(argFirst->ToString() ==
5154 argSecond->ToString());
dsinclair947c8732016-06-08 20:40:30 -07005155 return;
5156 }
5157
5158 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5159 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5160 args.GetReturnValue()->SetInteger((first == second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005161}
dsinclair48d91dd2016-05-31 11:54:01 -07005162
5163// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005164void CXFA_FM2JSContext::notequality_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005165 const CFX_ByteStringC& szFuncName,
5166 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005167 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005168 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005169 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005170 }
dsinclair947c8732016-06-08 20:40:30 -07005171
5172 if (fm_ref_equal(pThis, args)) {
5173 args.GetReturnValue()->SetInteger(0);
5174 return;
5175 }
5176
5177 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5178 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5179 if (argFirst->IsNull() || argSecond->IsNull()) {
5180 args.GetReturnValue()->SetInteger(
5181 (argFirst->IsNull() && argSecond->IsNull()) ? 0 : 1);
5182 return;
5183 }
5184
5185 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair2f5582f2016-06-09 11:48:23 -07005186 args.GetReturnValue()->SetInteger(argFirst->ToString() !=
5187 argSecond->ToString());
dsinclair947c8732016-06-08 20:40:30 -07005188 return;
5189 }
5190
5191 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5192 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5193 args.GetReturnValue()->SetInteger(first != second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005194}
dsinclair48d91dd2016-05-31 11:54:01 -07005195
5196// static
tsepezd19e9122016-11-02 15:43:18 -07005197bool CXFA_FM2JSContext::fm_ref_equal(CFXJSE_Value* pThis,
5198 CFXJSE_Arguments& args) {
dsinclair86fad992016-05-31 11:34:04 -07005199 std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0);
5200 std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1);
dsinclair947c8732016-06-08 20:40:30 -07005201 if (!argFirst->IsArray() || !argSecond->IsArray())
tsepezd19e9122016-11-02 15:43:18 -07005202 return false;
dsinclair947c8732016-06-08 20:40:30 -07005203
5204 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
5205 std::unique_ptr<CFXJSE_Value> firstFlagValue(new CFXJSE_Value(pIsolate));
5206 std::unique_ptr<CFXJSE_Value> secondFlagValue(new CFXJSE_Value(pIsolate));
5207 argFirst->GetObjectPropertyByIdx(0, firstFlagValue.get());
5208 argSecond->GetObjectPropertyByIdx(0, secondFlagValue.get());
5209 if (firstFlagValue->ToInteger() != 3 || secondFlagValue->ToInteger() != 3)
tsepezd19e9122016-11-02 15:43:18 -07005210 return false;
dsinclair947c8732016-06-08 20:40:30 -07005211
5212 std::unique_ptr<CFXJSE_Value> firstJSObject(new CFXJSE_Value(pIsolate));
5213 std::unique_ptr<CFXJSE_Value> secondJSObject(new CFXJSE_Value(pIsolate));
5214 argFirst->GetObjectPropertyByIdx(2, firstJSObject.get());
5215 argSecond->GetObjectPropertyByIdx(2, secondJSObject.get());
5216 if (firstJSObject->IsNull() || secondJSObject->IsNull())
tsepezd19e9122016-11-02 15:43:18 -07005217 return false;
dsinclair947c8732016-06-08 20:40:30 -07005218
5219 return (firstJSObject->ToHostObject(nullptr) ==
5220 secondJSObject->ToHostObject(nullptr));
Dan Sinclair1770c022016-03-14 14:14:16 -04005221}
dsinclair48d91dd2016-05-31 11:54:01 -07005222
5223// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005224void CXFA_FM2JSContext::less_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005225 const CFX_ByteStringC& szFuncName,
5226 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005227 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005228 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005229 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005230 }
dsinclair947c8732016-06-08 20:40:30 -07005231
5232 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5233 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5234 if (argFirst->IsNull() || argSecond->IsNull()) {
5235 args.GetReturnValue()->SetInteger(0);
5236 return;
5237 }
5238
5239 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005240 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005241 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == -1);
dsinclair947c8732016-06-08 20:40:30 -07005242 return;
5243 }
5244
5245 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5246 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5247 args.GetReturnValue()->SetInteger((first < second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005248}
dsinclair48d91dd2016-05-31 11:54:01 -07005249
5250// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005251void CXFA_FM2JSContext::lessequal_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005252 const CFX_ByteStringC& szFuncName,
5253 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005254 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005255 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005256 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005257 }
dsinclair947c8732016-06-08 20:40:30 -07005258
5259 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5260 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5261 if (argFirst->IsNull() || argSecond->IsNull()) {
5262 args.GetReturnValue()->SetInteger(
5263 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5264 return;
5265 }
5266
5267 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005268 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005269 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != 1);
dsinclair947c8732016-06-08 20:40:30 -07005270 return;
5271 }
5272
5273 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5274 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5275 args.GetReturnValue()->SetInteger((first <= second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005276}
dsinclair48d91dd2016-05-31 11:54:01 -07005277
5278// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005279void CXFA_FM2JSContext::greater_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005280 const CFX_ByteStringC& szFuncName,
5281 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005282 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005283 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005284 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005285 }
dsinclair947c8732016-06-08 20:40:30 -07005286
5287 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5288 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5289 if (argFirst->IsNull() || argSecond->IsNull()) {
5290 args.GetReturnValue()->SetInteger(0);
5291 return;
5292 }
5293
5294 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005295 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005296 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == 1);
dsinclair947c8732016-06-08 20:40:30 -07005297 return;
5298 }
5299
5300 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5301 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5302 args.GetReturnValue()->SetInteger((first > second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005303}
dsinclair48d91dd2016-05-31 11:54:01 -07005304
5305// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005306void CXFA_FM2JSContext::greaterequal_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005307 const CFX_ByteStringC& szFuncName,
5308 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005309 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005310 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005311 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005312 }
dsinclair947c8732016-06-08 20:40:30 -07005313
5314 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5315 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5316 if (argFirst->IsNull() || argSecond->IsNull()) {
5317 args.GetReturnValue()->SetInteger(
5318 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5319 return;
5320 }
5321
5322 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005323 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005324 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != -1);
dsinclair947c8732016-06-08 20:40:30 -07005325 return;
5326 }
5327
5328 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5329 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5330 args.GetReturnValue()->SetInteger((first >= second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005331}
dsinclair48d91dd2016-05-31 11:54:01 -07005332
5333// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005334void CXFA_FM2JSContext::plus_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005335 const CFX_ByteStringC& szFuncName,
5336 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005337 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005338 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005339 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005340 }
dsinclair947c8732016-06-08 20:40:30 -07005341
5342 std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0);
5343 std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1);
5344 if (ValueIsNull(pThis, argFirst.get()) &&
5345 ValueIsNull(pThis, argSecond.get())) {
5346 args.GetReturnValue()->SetNull();
5347 return;
5348 }
5349
5350 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5351 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5352 args.GetReturnValue()->SetDouble(first + second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005353}
dsinclair48d91dd2016-05-31 11:54:01 -07005354
5355// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005356void CXFA_FM2JSContext::minus_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005357 const CFX_ByteStringC& szFuncName,
5358 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005359 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005360 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005361 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005362 }
dsinclair947c8732016-06-08 20:40:30 -07005363
5364 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5365 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5366 if (argFirst->IsNull() && argSecond->IsNull()) {
5367 args.GetReturnValue()->SetNull();
5368 return;
5369 }
5370
5371 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5372 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5373 args.GetReturnValue()->SetDouble(first - second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005374}
dsinclair48d91dd2016-05-31 11:54:01 -07005375
5376// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005377void CXFA_FM2JSContext::multiple_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005378 const CFX_ByteStringC& szFuncName,
5379 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005380 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005381 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005382 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005383 }
dsinclair947c8732016-06-08 20:40:30 -07005384
5385 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5386 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5387 if (argFirst->IsNull() && argSecond->IsNull()) {
5388 args.GetReturnValue()->SetNull();
5389 return;
5390 }
5391
5392 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5393 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5394 args.GetReturnValue()->SetDouble(first * second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005395}
dsinclair48d91dd2016-05-31 11:54:01 -07005396
5397// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005398void CXFA_FM2JSContext::divide_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005399 const CFX_ByteStringC& szFuncName,
5400 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005401 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07005402 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07005403 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005404 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005405 }
dsinclair947c8732016-06-08 20:40:30 -07005406
5407 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5408 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5409 if (argFirst->IsNull() && argSecond->IsNull()) {
5410 args.GetReturnValue()->SetNull();
5411 return;
5412 }
5413
5414 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5415 if (second == 0.0) {
5416 pContext->ThrowException(XFA_IDS_DIVIDE_ZERO);
5417 return;
5418 }
5419
5420 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5421 args.GetReturnValue()->SetDouble(first / second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005422}
dsinclair48d91dd2016-05-31 11:54:01 -07005423
5424// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005425void CXFA_FM2JSContext::positive_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005426 const CFX_ByteStringC& szFuncName,
5427 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005428 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005429 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005430 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005431 }
dsinclair947c8732016-06-08 20:40:30 -07005432
5433 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5434 if (argOne->IsNull()) {
5435 args.GetReturnValue()->SetNull();
5436 return;
5437 }
5438 args.GetReturnValue()->SetDouble(0.0 + ValueToDouble(pThis, argOne.get()));
Dan Sinclair1770c022016-03-14 14:14:16 -04005439}
dsinclair48d91dd2016-05-31 11:54:01 -07005440
5441// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005442void CXFA_FM2JSContext::negative_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005443 const CFX_ByteStringC& szFuncName,
5444 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005445 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005446 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005447 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005448 }
dsinclair947c8732016-06-08 20:40:30 -07005449
5450 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5451 if (argOne->IsNull()) {
5452 args.GetReturnValue()->SetNull();
5453 return;
5454 }
5455 args.GetReturnValue()->SetDouble(0.0 - ValueToDouble(pThis, argOne.get()));
Dan Sinclair1770c022016-03-14 14:14:16 -04005456}
dsinclair48d91dd2016-05-31 11:54:01 -07005457
5458// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005459void CXFA_FM2JSContext::logical_not_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005460 const CFX_ByteStringC& szFuncName,
5461 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005462 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005463 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005464 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005465 }
dsinclair947c8732016-06-08 20:40:30 -07005466
5467 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5468 if (argOne->IsNull()) {
5469 args.GetReturnValue()->SetNull();
5470 return;
5471 }
5472
5473 FX_DOUBLE first = ValueToDouble(pThis, argOne.get());
5474 args.GetReturnValue()->SetInteger((first == 0.0) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005475}
dsinclair48d91dd2016-05-31 11:54:01 -07005476
5477// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005478void CXFA_FM2JSContext::dot_accessor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005479 const CFX_ByteStringC& szFuncName,
5480 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005481 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07005482 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005483 int32_t argc = args.GetLength();
dsinclairbd136fb2016-06-09 11:47:51 -07005484 if (argc < 4 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07005485 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005486 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005487 }
dsinclairbd136fb2016-06-09 11:47:51 -07005488
5489 bool bIsStar = true;
5490 int32_t iIndexValue = 0;
5491 if (argc > 4) {
5492 bIsStar = false;
5493 iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
5494 }
5495
5496 CFX_ByteString szName = args.GetUTF8String(2);
5497 CFX_ByteString szSomExp;
5498 GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue,
5499 bIsStar, szSomExp);
5500
5501 std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
5502 if (argAccessor->IsArray()) {
5503 std::unique_ptr<CFXJSE_Value> pLengthValue(new CFXJSE_Value(pIsolate));
5504 argAccessor->GetObjectProperty("length", pLengthValue.get());
5505 int32_t iLength = pLengthValue->ToInteger();
5506 CFXJSE_Value*** hResolveValues = FX_Alloc(CFXJSE_Value**, iLength - 2);
5507 int32_t* iSizes = FX_Alloc(int32_t, iLength - 2);
5508 for (int32_t i = 0; i < (iLength - 2); i++)
5509 iSizes[i] = 0;
5510
5511 std::unique_ptr<CFXJSE_Value> hJSObjValue(new CFXJSE_Value(pIsolate));
tsepezd19e9122016-11-02 15:43:18 -07005512 bool bAttribute = false;
dsinclairbd136fb2016-06-09 11:47:51 -07005513 int32_t iCounter = 0;
5514 for (int32_t i = 2; i < iLength; i++) {
5515 argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
5516
5517 XFA_RESOLVENODE_RS resoveNodeRS;
5518 if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07005519 resoveNodeRS, true, szName.IsEmpty()) > 0) {
dsinclairbd136fb2016-06-09 11:47:51 -07005520 ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(),
5521 hResolveValues[i - 2], iSizes[i - 2], bAttribute);
5522 iCounter += iSizes[i - 2];
5523 }
5524 }
5525 if (iCounter < 1) {
5526 CFX_WideString wsPropertyName =
5527 CFX_WideString::FromUTF8(szName.AsStringC());
5528 CFX_WideString wsSomExpression =
5529 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5530 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5531 wsPropertyName.c_str(), wsSomExpression.c_str());
5532 return;
5533 }
5534
5535 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iCounter + 2);
5536 for (int32_t i = 0; i < (iCounter + 2); i++)
5537 rgValues[i] = new CFXJSE_Value(pIsolate);
5538
5539 rgValues[0]->SetInteger(1);
5540 if (bAttribute)
5541 rgValues[1]->SetString(szName.AsStringC());
5542 else
5543 rgValues[1]->SetNull();
5544
5545 int32_t iIndex = 2;
5546 for (int32_t i = 0; i < iLength - 2; i++) {
5547 for (int32_t j = 0; j < iSizes[i]; j++) {
5548 rgValues[iIndex]->Assign(hResolveValues[i][j]);
5549 iIndex++;
5550 }
5551 }
5552 args.GetReturnValue()->SetArray(iCounter + 2, rgValues);
5553
5554 for (int32_t i = 0; i < (iCounter + 2); i++)
5555 delete rgValues[i];
5556 FX_Free(rgValues);
5557
5558 for (int32_t i = 0; i < iLength - 2; i++) {
5559 for (int32_t j = 0; j < iSizes[i]; j++)
5560 delete hResolveValues[i][j];
5561
5562 if (iSizes[i] > 0)
5563 FX_Free(hResolveValues[i]);
5564 }
5565 FX_Free(hResolveValues);
5566 FX_Free(iSizes);
5567
5568 return;
5569 }
5570
5571 XFA_RESOLVENODE_RS resoveNodeRS;
5572 int32_t iRet = 0;
5573 CFX_ByteString bsAccessorName = args.GetUTF8String(1);
5574 if (argAccessor->IsObject() ||
5575 (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
5576 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07005577 resoveNodeRS, true, szName.IsEmpty());
dsinclairbd136fb2016-06-09 11:47:51 -07005578 } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
dsinclair38fd8442016-09-15 10:15:32 -07005579 GetObjectForName(pThis, argAccessor.get(),
5580 bsAccessorName.AsStringC())) {
dsinclairbd136fb2016-06-09 11:47:51 -07005581 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07005582 resoveNodeRS, true, szName.IsEmpty());
dsinclairbd136fb2016-06-09 11:47:51 -07005583 }
5584 if (iRet < 1) {
5585 CFX_WideString wsPropertyName =
5586 CFX_WideString::FromUTF8(szName.AsStringC());
5587 CFX_WideString wsSomExpression =
5588 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5589 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5590 wsPropertyName.c_str(), wsSomExpression.c_str());
5591 return;
5592 }
5593
5594 CFXJSE_Value** hResolveValues;
5595 int32_t iSize = 0;
tsepezd19e9122016-11-02 15:43:18 -07005596 bool bAttribute = false;
dsinclairbd136fb2016-06-09 11:47:51 -07005597 ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), hResolveValues,
5598 iSize, bAttribute);
5599 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iSize + 2);
5600 for (int32_t i = 0; i < (iSize + 2); i++)
5601 rgValues[i] = new CFXJSE_Value(pIsolate);
5602
5603 rgValues[0]->SetInteger(1);
5604 if (bAttribute)
5605 rgValues[1]->SetString(szName.AsStringC());
5606 else
5607 rgValues[1]->SetNull();
5608
5609 for (int32_t i = 0; i < iSize; i++)
5610 rgValues[i + 2]->Assign(hResolveValues[i]);
5611
5612 args.GetReturnValue()->SetArray(iSize + 2, rgValues);
5613 for (int32_t i = 0; i < (iSize + 2); i++)
5614 delete rgValues[i];
5615 FX_Free(rgValues);
5616
5617 for (int32_t i = 0; i < iSize; i++)
5618 delete hResolveValues[i];
5619 FX_Free(hResolveValues);
Dan Sinclair1770c022016-03-14 14:14:16 -04005620}
dsinclair48d91dd2016-05-31 11:54:01 -07005621
5622// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005623void CXFA_FM2JSContext::dotdot_accessor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005624 const CFX_ByteStringC& szFuncName,
5625 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005626 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07005627 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005628 int32_t argc = args.GetLength();
dsinclairbd136fb2016-06-09 11:47:51 -07005629 if (argc < 4 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07005630 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005631 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005632 }
dsinclairbd136fb2016-06-09 11:47:51 -07005633
5634 bool bIsStar = true;
5635 int32_t iIndexValue = 0;
5636 if (argc > 4) {
5637 bIsStar = false;
5638 iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
5639 }
5640
5641 CFX_ByteString szSomExp;
5642 CFX_ByteString szName = args.GetUTF8String(2);
5643 GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue,
5644 bIsStar, szSomExp);
5645
5646 std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
5647 if (argAccessor->IsArray()) {
5648 std::unique_ptr<CFXJSE_Value> pLengthValue(new CFXJSE_Value(pIsolate));
5649 argAccessor->GetObjectProperty("length", pLengthValue.get());
5650 int32_t iLength = pLengthValue->ToInteger();
5651 int32_t iCounter = 0;
5652
5653 CFXJSE_Value*** hResolveValues = FX_Alloc(CFXJSE_Value**, iLength - 2);
5654 int32_t* iSizes = FX_Alloc(int32_t, iLength - 2);
5655 std::unique_ptr<CFXJSE_Value> hJSObjValue(new CFXJSE_Value(pIsolate));
tsepezd19e9122016-11-02 15:43:18 -07005656 bool bAttribute = false;
dsinclairbd136fb2016-06-09 11:47:51 -07005657 for (int32_t i = 2; i < iLength; i++) {
5658 argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
5659 XFA_RESOLVENODE_RS resoveNodeRS;
5660 if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07005661 resoveNodeRS, false) > 0) {
dsinclairbd136fb2016-06-09 11:47:51 -07005662 ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(),
5663 hResolveValues[i - 2], iSizes[i - 2], bAttribute);
5664 iCounter += iSizes[i - 2];
5665 }
5666 }
5667 if (iCounter < 1) {
5668 CFX_WideString wsPropertyName =
5669 CFX_WideString::FromUTF8(szName.AsStringC());
5670 CFX_WideString wsSomExpression =
5671 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5672 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5673 wsPropertyName.c_str(), wsSomExpression.c_str());
5674 return;
5675 }
5676
5677 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iCounter + 2);
5678 for (int32_t i = 0; i < (iCounter + 2); i++)
5679 rgValues[i] = new CFXJSE_Value(pIsolate);
5680
5681 rgValues[0]->SetInteger(1);
5682 if (bAttribute)
5683 rgValues[1]->SetString(szName.AsStringC());
5684 else
5685 rgValues[1]->SetNull();
5686
5687 int32_t iIndex = 2;
5688 for (int32_t i = 0; i < iLength - 2; i++) {
5689 for (int32_t j = 0; j < iSizes[i]; j++) {
5690 rgValues[iIndex]->Assign(hResolveValues[i][j]);
5691 iIndex++;
5692 }
5693 }
5694 args.GetReturnValue()->SetArray(iCounter + 2, rgValues);
5695 for (int32_t i = 0; i < (iCounter + 2); i++)
5696 delete rgValues[i];
5697 FX_Free(rgValues);
5698
5699 for (int32_t i = 0; i < iLength - 2; i++) {
5700 for (int32_t j = 0; j < iSizes[i]; j++)
5701 delete hResolveValues[i][j];
5702 FX_Free(hResolveValues[i]);
5703 }
5704 FX_Free(hResolveValues);
5705 FX_Free(iSizes);
5706 return;
5707 }
5708
5709 XFA_RESOLVENODE_RS resoveNodeRS;
5710 int32_t iRet = 0;
5711 CFX_ByteString bsAccessorName = args.GetUTF8String(1);
5712 if (argAccessor->IsObject() ||
5713 (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
5714 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07005715 resoveNodeRS, false);
dsinclairbd136fb2016-06-09 11:47:51 -07005716 } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
dsinclair38fd8442016-09-15 10:15:32 -07005717 GetObjectForName(pThis, argAccessor.get(),
5718 bsAccessorName.AsStringC())) {
dsinclairbd136fb2016-06-09 11:47:51 -07005719 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
tsepezd19e9122016-11-02 15:43:18 -07005720 resoveNodeRS, false);
dsinclairbd136fb2016-06-09 11:47:51 -07005721 }
5722 if (iRet < 1) {
5723 CFX_WideString wsPropertyName =
5724 CFX_WideString::FromUTF8(szName.AsStringC());
5725 CFX_WideString wsSomExpression =
5726 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5727 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5728 wsPropertyName.c_str(), wsSomExpression.c_str());
5729 return;
5730 }
5731
5732 CFXJSE_Value** hResolveValues;
5733 int32_t iSize = 0;
tsepezd19e9122016-11-02 15:43:18 -07005734 bool bAttribute = false;
dsinclairbd136fb2016-06-09 11:47:51 -07005735 ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), hResolveValues,
5736 iSize, bAttribute);
5737 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iSize + 2);
5738 for (int32_t i = 0; i < (iSize + 2); i++)
5739 rgValues[i] = new CFXJSE_Value(pIsolate);
5740
5741 rgValues[0]->SetInteger(1);
5742 if (bAttribute)
5743 rgValues[1]->SetString(szName.AsStringC());
5744 else
5745 rgValues[1]->SetNull();
5746
5747 for (int32_t i = 0; i < iSize; i++)
5748 rgValues[i + 2]->Assign(hResolveValues[i]);
5749
5750 args.GetReturnValue()->SetArray(iSize + 2, rgValues);
5751
5752 for (int32_t i = 0; i < (iSize + 2); i++)
5753 delete rgValues[i];
5754 FX_Free(rgValues);
5755
5756 for (int32_t i = 0; i < iSize; i++)
5757 delete hResolveValues[i];
5758 FX_Free(hResolveValues);
Dan Sinclair1770c022016-03-14 14:14:16 -04005759}
dsinclair48d91dd2016-05-31 11:54:01 -07005760
5761// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005762void CXFA_FM2JSContext::eval_translation(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005763 const CFX_ByteStringC& szFuncName,
5764 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005765 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005766 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005767 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Eval");
dsinclairbd136fb2016-06-09 11:47:51 -07005768 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005769 }
dsinclairbd136fb2016-06-09 11:47:51 -07005770
5771 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5772 CFX_ByteString argString;
5773 ValueToUTF8String(argOne.get(), argString);
5774 if (argString.IsEmpty()) {
5775 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
5776 return;
5777 }
5778
5779 CFX_WideString scriptString = CFX_WideString::FromUTF8(argString.AsStringC());
5780 CFX_WideTextBuf wsJavaScriptBuf;
5781 CFX_WideString wsError;
5782 CXFA_FM2JSContext::Translate(scriptString.AsStringC(), wsJavaScriptBuf,
5783 wsError);
5784 if (!wsError.IsEmpty()) {
5785 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5786 return;
5787 }
5788
5789 CFX_WideString javaScript = wsJavaScriptBuf.MakeString();
5790 args.GetReturnValue()->SetString(
5791 FX_UTF8Encode(javaScript.c_str(), javaScript.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04005792}
dsinclair48d91dd2016-05-31 11:54:01 -07005793
5794// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005795void CXFA_FM2JSContext::is_fm_object(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005796 const CFX_ByteStringC& szFuncName,
5797 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005798 if (args.GetLength() != 1) {
tsepezd19e9122016-11-02 15:43:18 -07005799 args.GetReturnValue()->SetBoolean(false);
dsinclairbd136fb2016-06-09 11:47:51 -07005800 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005801 }
dsinclairbd136fb2016-06-09 11:47:51 -07005802
5803 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5804 args.GetReturnValue()->SetBoolean(argOne->IsObject());
Dan Sinclair1770c022016-03-14 14:14:16 -04005805}
dsinclair48d91dd2016-05-31 11:54:01 -07005806
5807// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005808void CXFA_FM2JSContext::is_fm_array(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005809 const CFX_ByteStringC& szFuncName,
5810 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005811 if (args.GetLength() != 1) {
tsepezd19e9122016-11-02 15:43:18 -07005812 args.GetReturnValue()->SetBoolean(false);
dsinclairbd136fb2016-06-09 11:47:51 -07005813 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005814 }
dsinclairbd136fb2016-06-09 11:47:51 -07005815
5816 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5817 args.GetReturnValue()->SetBoolean(argOne->IsArray());
Dan Sinclair1770c022016-03-14 14:14:16 -04005818}
dsinclair48d91dd2016-05-31 11:54:01 -07005819
5820// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005821void CXFA_FM2JSContext::get_fm_value(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005822 const CFX_ByteStringC& szFuncName,
5823 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005824 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005825 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005826 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005827 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005828 }
dsinclairbd136fb2016-06-09 11:47:51 -07005829
5830 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5831 if (argOne->IsArray()) {
5832 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5833 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
5834 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
5835 argOne->GetObjectPropertyByIdx(1, propertyValue.get());
5836 argOne->GetObjectPropertyByIdx(2, jsObjectValue.get());
5837 if (propertyValue->IsNull()) {
5838 GetObjectDefaultValue(jsObjectValue.get(), args.GetReturnValue());
5839 return;
5840 }
5841
dsinclair2f5582f2016-06-09 11:48:23 -07005842 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07005843 args.GetReturnValue());
5844 return;
5845 }
5846
5847 if (argOne->IsObject()) {
5848 GetObjectDefaultValue(argOne.get(), args.GetReturnValue());
5849 return;
5850 }
5851
5852 args.GetReturnValue()->Assign(argOne.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005853}
dsinclair48d91dd2016-05-31 11:54:01 -07005854
5855// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005856void CXFA_FM2JSContext::get_fm_jsobj(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005857 const CFX_ByteStringC& szFuncName,
5858 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005859 if (args.GetLength() != 1) {
5860 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
5861 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005862 }
dsinclairbd136fb2016-06-09 11:47:51 -07005863
5864 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5865 if (!argOne->IsArray()) {
5866 args.GetReturnValue()->Assign(argOne.get());
5867 return;
5868 }
5869
5870#ifndef NDEBUG
5871 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
5872 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5873 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
5874 argOne->GetObjectProperty("length", lengthValue.get());
5875 ASSERT(lengthValue->ToInteger() >= 3);
5876#endif
5877
5878 argOne->GetObjectPropertyByIdx(2, args.GetReturnValue());
Dan Sinclair1770c022016-03-14 14:14:16 -04005879}
dsinclair48d91dd2016-05-31 11:54:01 -07005880
5881// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005882void CXFA_FM2JSContext::fm_var_filter(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005883 const CFX_ByteStringC& szFuncName,
5884 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005885 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005886 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005887 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005888 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005889 }
dsinclairbd136fb2016-06-09 11:47:51 -07005890
5891 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5892 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5893 if (!argOne->IsArray()) {
5894 std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0);
5895 args.GetReturnValue()->Assign(simpleValue.get());
5896 return;
5897 }
5898
5899#ifndef NDEBUG
5900 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
5901 argOne->GetObjectProperty("length", lengthValue.get());
5902 ASSERT(lengthValue->ToInteger() >= 3);
5903#endif
5904
5905 std::unique_ptr<CFXJSE_Value> flagsValue(new CFXJSE_Value(pIsolate));
5906 argOne->GetObjectPropertyByIdx(0, flagsValue.get());
5907 int32_t iFlags = flagsValue->ToInteger();
5908 if (iFlags != 3 && iFlags != 4) {
5909 std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0);
5910 args.GetReturnValue()->Assign(simpleValue.get());
5911 return;
5912 }
5913
5914 if (iFlags == 4) {
5915 CFXJSE_Value* rgValues[3];
5916 for (int32_t i = 0; i < 3; i++)
5917 rgValues[i] = new CFXJSE_Value(pIsolate);
5918
5919 rgValues[0]->SetInteger(3);
5920 rgValues[1]->SetNull();
5921 rgValues[2]->SetNull();
5922 args.GetReturnValue()->SetArray(3, rgValues);
5923 for (int32_t i = 0; i < 3; i++)
5924 delete rgValues[i];
5925
5926 return;
5927 }
5928
5929 std::unique_ptr<CFXJSE_Value> objectValue(new CFXJSE_Value(pIsolate));
5930 argOne->GetObjectPropertyByIdx(2, objectValue.get());
5931 if (objectValue->IsNull()) {
5932 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5933 return;
5934 }
5935 args.GetReturnValue()->Assign(argOne.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005936}
dsinclair48d91dd2016-05-31 11:54:01 -07005937
5938// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005939void CXFA_FM2JSContext::concat_fm_object(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005940 const CFX_ByteStringC& szFuncName,
5941 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005942 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005943 uint32_t iLength = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07005944 int32_t argc = args.GetLength();
dsinclair86fad992016-05-31 11:34:04 -07005945 std::vector<std::unique_ptr<CFXJSE_Value>> argValues;
dsinclair48d91dd2016-05-31 11:54:01 -07005946 for (int32_t i = 0; i < argc; i++) {
dsinclair86fad992016-05-31 11:34:04 -07005947 argValues.push_back(args.GetValue(i));
dsinclair769b1372016-06-08 13:12:41 -07005948 if (argValues[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005949 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005950 argValues[i]->GetObjectProperty("length", lengthValue.get());
5951 int32_t length = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04005952 iLength = iLength + ((length > 2) ? (length - 2) : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005953 }
5954 iLength += 1;
5955 }
dsinclairbd136fb2016-06-09 11:47:51 -07005956
dsinclair12a6b0c2016-05-26 11:14:08 -07005957 CFXJSE_Value** returnValues = FX_Alloc(CFXJSE_Value*, iLength);
dsinclair86fad992016-05-31 11:34:04 -07005958 for (int32_t i = 0; i < (int32_t)iLength; i++)
5959 returnValues[i] = new CFXJSE_Value(pIsolate);
5960
Dan Sinclair1770c022016-03-14 14:14:16 -04005961 int32_t index = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07005962 for (int32_t i = 0; i < argc; i++) {
dsinclair769b1372016-06-08 13:12:41 -07005963 if (argValues[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005964 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005965 argValues[i]->GetObjectProperty("length", lengthValue.get());
5966 int32_t length = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04005967 for (int32_t j = 2; j < length; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -07005968 argValues[i]->GetObjectPropertyByIdx(j, returnValues[index]);
Dan Sinclair1770c022016-03-14 14:14:16 -04005969 index++;
5970 }
Dan Sinclair1770c022016-03-14 14:14:16 -04005971 }
dsinclairf27aeec2016-06-07 19:36:18 -07005972 returnValues[index]->Assign(argValues[i].get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005973 index++;
5974 }
dsinclairf27aeec2016-06-07 19:36:18 -07005975 args.GetReturnValue()->SetArray(iLength, returnValues);
dsinclair86fad992016-05-31 11:34:04 -07005976 for (int32_t i = 0; i < (int32_t)iLength; i++)
5977 delete returnValues[i];
5978
Dan Sinclair1770c022016-03-14 14:14:16 -04005979 FX_Free(returnValues);
5980}
dsinclair48d91dd2016-05-31 11:54:01 -07005981
5982// static
dsinclair86fad992016-05-31 11:34:04 -07005983std::unique_ptr<CFXJSE_Value> CXFA_FM2JSContext::GetSimpleValue(
5984 CFXJSE_Value* pThis,
5985 CFXJSE_Arguments& args,
5986 uint32_t index) {
dsinclair8f3074b2016-06-02 17:45:25 -07005987 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair43854a52016-04-27 12:26:00 -07005988 ASSERT(index < (uint32_t)args.GetLength());
dsinclairbd136fb2016-06-09 11:47:51 -07005989
dsinclair86fad992016-05-31 11:34:04 -07005990 std::unique_ptr<CFXJSE_Value> argIndex = args.GetValue(index);
dsinclairbd136fb2016-06-09 11:47:51 -07005991 if (!argIndex->IsArray() && !argIndex->IsObject())
5992 return argIndex;
5993
dsinclair769b1372016-06-08 13:12:41 -07005994 if (argIndex->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005995 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005996 argIndex->GetObjectProperty("length", lengthValue.get());
5997 int32_t iLength = lengthValue->ToInteger();
dsinclair86fad992016-05-31 11:34:04 -07005998 std::unique_ptr<CFXJSE_Value> simpleValue(new CFXJSE_Value(pIsolate));
dsinclairbd136fb2016-06-09 11:47:51 -07005999 if (iLength < 3) {
dsinclairf27aeec2016-06-07 19:36:18 -07006000 simpleValue.get()->SetUndefined();
dsinclairbd136fb2016-06-09 11:47:51 -07006001 return simpleValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006002 }
dsinclairbd136fb2016-06-09 11:47:51 -07006003
6004 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6005 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6006 argIndex->GetObjectPropertyByIdx(1, propertyValue.get());
6007 argIndex->GetObjectPropertyByIdx(2, jsObjectValue.get());
6008 if (propertyValue->IsNull()) {
6009 GetObjectDefaultValue(jsObjectValue.get(), simpleValue.get());
6010 return simpleValue;
6011 }
6012
dsinclair2f5582f2016-06-09 11:48:23 -07006013 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006014 simpleValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006015 return simpleValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006016 }
dsinclairbd136fb2016-06-09 11:47:51 -07006017
6018 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6019 GetObjectDefaultValue(argIndex.get(), defaultValue.get());
6020 return defaultValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006021}
dsinclair12a6b0c2016-05-26 11:14:08 -07006022
dsinclair48d91dd2016-05-31 11:54:01 -07006023// static
tsepezd19e9122016-11-02 15:43:18 -07006024bool CXFA_FM2JSContext::ValueIsNull(CFXJSE_Value* pThis, CFXJSE_Value* arg) {
dsinclairbd136fb2016-06-09 11:47:51 -07006025 if (!arg || arg->IsNull())
tsepezd19e9122016-11-02 15:43:18 -07006026 return true;
dsinclairbd136fb2016-06-09 11:47:51 -07006027
6028 if (!arg->IsArray() && !arg->IsObject())
tsepezd19e9122016-11-02 15:43:18 -07006029 return false;
dsinclairbd136fb2016-06-09 11:47:51 -07006030
dsinclair8f3074b2016-06-02 17:45:25 -07006031 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclairbd136fb2016-06-09 11:47:51 -07006032 if (arg->IsArray()) {
dsinclair12a6b0c2016-05-26 11:14:08 -07006033 int32_t iLength = hvalue_get_array_length(pThis, arg);
dsinclairbd136fb2016-06-09 11:47:51 -07006034 if (iLength < 3)
tsepezd19e9122016-11-02 15:43:18 -07006035 return true;
dsinclairbd136fb2016-06-09 11:47:51 -07006036
6037 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6038 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6039 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6040 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
6041 if (propertyValue->IsNull()) {
6042 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6043 GetObjectDefaultValue(jsObjectValue.get(), defaultValue.get());
6044 return defaultValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006045 }
dsinclairbd136fb2016-06-09 11:47:51 -07006046
dsinclairbd136fb2016-06-09 11:47:51 -07006047 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -07006048 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006049 newPropertyValue.get());
6050 return newPropertyValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006051 }
dsinclairbd136fb2016-06-09 11:47:51 -07006052
6053 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6054 GetObjectDefaultValue(arg, defaultValue.get());
6055 return defaultValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006056}
dsinclair12a6b0c2016-05-26 11:14:08 -07006057
dsinclair48d91dd2016-05-31 11:54:01 -07006058// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006059int32_t CXFA_FM2JSContext::hvalue_get_array_length(CFXJSE_Value* pThis,
6060 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006061 if (!arg || !arg->IsArray())
6062 return 0;
6063
dsinclair8f3074b2016-06-02 17:45:25 -07006064 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006065 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
6066 arg->GetObjectProperty("length", lengthValue.get());
6067 return lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006068}
dsinclair48d91dd2016-05-31 11:54:01 -07006069
6070// static
tsepezd19e9122016-11-02 15:43:18 -07006071bool CXFA_FM2JSContext::simpleValueCompare(CFXJSE_Value* pThis,
6072 CFXJSE_Value* firstValue,
6073 CFXJSE_Value* secondValue) {
dsinclair769b1372016-06-08 13:12:41 -07006074 if (!firstValue)
tsepezd19e9122016-11-02 15:43:18 -07006075 return false;
dsinclair769b1372016-06-08 13:12:41 -07006076
dsinclair769b1372016-06-08 13:12:41 -07006077 if (firstValue->IsString()) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006078 CFX_ByteString firstString, secondString;
dsinclair12a6b0c2016-05-26 11:14:08 -07006079 ValueToUTF8String(firstValue, firstString);
6080 ValueToUTF8String(secondValue, secondString);
dsinclairbd136fb2016-06-09 11:47:51 -07006081 return firstString == secondString;
6082 }
6083 if (firstValue->IsNumber()) {
dsinclair12a6b0c2016-05-26 11:14:08 -07006084 FX_FLOAT first = ValueToFloat(pThis, firstValue);
6085 FX_FLOAT second = ValueToFloat(pThis, secondValue);
dsinclairbd136fb2016-06-09 11:47:51 -07006086 return (first == second);
Dan Sinclair1770c022016-03-14 14:14:16 -04006087 }
dsinclairbd136fb2016-06-09 11:47:51 -07006088 if (firstValue->IsBoolean())
6089 return (firstValue->ToBoolean() == secondValue->ToBoolean());
6090
6091 return firstValue->IsNull() && secondValue && secondValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006092}
dsinclair48d91dd2016-05-31 11:54:01 -07006093
6094// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006095void CXFA_FM2JSContext::unfoldArgs(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04006096 CFXJSE_Arguments& args,
dsinclair12a6b0c2016-05-26 11:14:08 -07006097 CFXJSE_Value**& resultValues,
Dan Sinclair1770c022016-03-14 14:14:16 -04006098 int32_t& iCount,
6099 int32_t iStart) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006100 iCount = 0;
dsinclairbd136fb2016-06-09 11:47:51 -07006101
6102 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04006103 int32_t argc = args.GetLength();
dsinclair86fad992016-05-31 11:34:04 -07006104 std::vector<std::unique_ptr<CFXJSE_Value>> argsValue;
6105 for (int32_t i = 0; i < argc - iStart; i++) {
6106 argsValue.push_back(args.GetValue(i + iStart));
dsinclair769b1372016-06-08 13:12:41 -07006107 if (argsValue[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006108 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006109 argsValue[i]->GetObjectProperty("length", lengthValue.get());
6110 int32_t iLength = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006111 iCount += ((iLength > 2) ? (iLength - 2) : 0);
6112 } else {
6113 iCount += 1;
6114 }
6115 }
dsinclair12a6b0c2016-05-26 11:14:08 -07006116 resultValues = FX_Alloc(CFXJSE_Value*, iCount);
dsinclair86fad992016-05-31 11:34:04 -07006117 for (int32_t i = 0; i < iCount; i++)
6118 resultValues[i] = new CFXJSE_Value(pIsolate);
6119
Dan Sinclair1770c022016-03-14 14:14:16 -04006120 int32_t index = 0;
dsinclair86fad992016-05-31 11:34:04 -07006121 for (int32_t i = 0; i < argc - iStart; i++) {
dsinclair769b1372016-06-08 13:12:41 -07006122 if (argsValue[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006123 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006124 argsValue[i]->GetObjectProperty("length", lengthValue.get());
6125 int32_t iLength = lengthValue->ToInteger();
dsinclairbd136fb2016-06-09 11:47:51 -07006126 if (iLength < 3)
6127 continue;
6128
6129 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6130 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6131 argsValue[i]->GetObjectPropertyByIdx(1, propertyValue.get());
6132 if (propertyValue->IsNull()) {
6133 for (int32_t j = 2; j < iLength; j++) {
6134 argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get());
6135 GetObjectDefaultValue(jsObjectValue.get(), resultValues[index]);
6136 index++;
6137 }
6138 } else {
dsinclairbd136fb2016-06-09 11:47:51 -07006139 for (int32_t j = 2; j < iLength; j++) {
6140 argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -07006141 jsObjectValue->GetObjectProperty(
6142 propertyValue->ToString().AsStringC(), resultValues[index]);
dsinclairbd136fb2016-06-09 11:47:51 -07006143 index++;
Dan Sinclair1770c022016-03-14 14:14:16 -04006144 }
Dan Sinclair1770c022016-03-14 14:14:16 -04006145 }
dsinclair769b1372016-06-08 13:12:41 -07006146 } else if (argsValue[i]->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006147 GetObjectDefaultValue(argsValue[i].get(), resultValues[index]);
Dan Sinclair1770c022016-03-14 14:14:16 -04006148 index++;
6149 } else {
dsinclairf27aeec2016-06-07 19:36:18 -07006150 resultValues[index]->Assign(argsValue[i].get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006151 index++;
6152 }
6153 }
Dan Sinclair1770c022016-03-14 14:14:16 -04006154}
dsinclair86fad992016-05-31 11:34:04 -07006155
dsinclair48d91dd2016-05-31 11:54:01 -07006156// static
dsinclair8f3074b2016-06-02 17:45:25 -07006157void CXFA_FM2JSContext::GetObjectDefaultValue(CFXJSE_Value* pValue,
dsinclair12a6b0c2016-05-26 11:14:08 -07006158 CFXJSE_Value* pDefaultValue) {
dsinclair8f3074b2016-06-02 17:45:25 -07006159 CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr));
6160 if (!pNode) {
dsinclairf27aeec2016-06-07 19:36:18 -07006161 pDefaultValue->SetNull();
dsinclair8f3074b2016-06-02 17:45:25 -07006162 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04006163 }
tsepezd19e9122016-11-02 15:43:18 -07006164 pNode->Script_Som_DefaultValue(pDefaultValue, false, (XFA_ATTRIBUTE)-1);
Dan Sinclair1770c022016-03-14 14:14:16 -04006165}
dsinclair48d91dd2016-05-31 11:54:01 -07006166
6167// static
tsepezd19e9122016-11-02 15:43:18 -07006168bool CXFA_FM2JSContext::SetObjectDefaultValue(CFXJSE_Value* pValue,
6169 CFXJSE_Value* hNewValue) {
dsinclair8f3074b2016-06-02 17:45:25 -07006170 CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr));
6171 if (!pNode)
tsepezd19e9122016-11-02 15:43:18 -07006172 return false;
dsinclair8f3074b2016-06-02 17:45:25 -07006173
tsepezd19e9122016-11-02 15:43:18 -07006174 pNode->Script_Som_DefaultValue(hNewValue, true, (XFA_ATTRIBUTE)-1);
6175 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04006176}
dsinclair48d91dd2016-05-31 11:54:01 -07006177
6178// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006179void CXFA_FM2JSContext::GenerateSomExpression(const CFX_ByteStringC& szName,
6180 int32_t iIndexFlags,
6181 int32_t iIndexValue,
dsinclairbd136fb2016-06-09 11:47:51 -07006182 bool bIsStar,
Dan Sinclair1770c022016-03-14 14:14:16 -04006183 CFX_ByteString& szSomExp) {
6184 if (bIsStar) {
6185 szSomExp = szName + "[*]";
6186 return;
6187 }
6188 if (iIndexFlags == 0) {
6189 szSomExp = szName;
6190 return;
6191 }
6192 if (iIndexFlags == 1 || iIndexValue == 0) {
6193 szSomExp = szName + "[" +
6194 CFX_ByteString::FormatInteger(iIndexValue, FXFORMAT_SIGNED) +
6195 "]";
6196 } else if (iIndexFlags == 2) {
6197 szSomExp = (iIndexValue < 0) ? (szName + "[-") : (szName + "[+");
6198 iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue;
6199 szSomExp += CFX_ByteString::FormatInteger(iIndexValue);
6200 szSomExp += "]";
6201 } else {
6202 szSomExp = (iIndexValue < 0) ? (szName + "[") : (szName + "[-");
6203 iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue;
6204 szSomExp += CFX_ByteString::FormatInteger(iIndexValue);
6205 szSomExp += "]";
6206 }
6207}
dsinclair48d91dd2016-05-31 11:54:01 -07006208
6209// static
tsepezd19e9122016-11-02 15:43:18 -07006210bool CXFA_FM2JSContext::GetObjectForName(
dsinclair12a6b0c2016-05-26 11:14:08 -07006211 CFXJSE_Value* pThis,
6212 CFXJSE_Value* accessorValue,
Dan Sinclair1770c022016-03-14 14:14:16 -04006213 const CFX_ByteStringC& szAccessorName) {
dsinclair8f3074b2016-06-02 17:45:25 -07006214 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclairbd136fb2016-06-09 11:47:51 -07006215 if (!pDoc)
tsepezd19e9122016-11-02 15:43:18 -07006216 return false;
dsinclairbd136fb2016-06-09 11:47:51 -07006217
dsinclairdf4bc592016-03-31 20:34:43 -07006218 CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext();
Dan Sinclair1770c022016-03-14 14:14:16 -04006219 XFA_RESOLVENODE_RS resoveNodeRS;
tsepez736f28a2016-03-25 14:19:51 -07006220 uint32_t dwFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
Dan Sinclair1770c022016-03-14 14:14:16 -04006221 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
6222 int32_t iRet = pScriptContext->ResolveObjects(
6223 pScriptContext->GetThisObject(),
tsepez4c3debb2016-04-08 12:20:38 -07006224 CFX_WideString::FromUTF8(szAccessorName).AsStringC(), resoveNodeRS,
tsepez6fe7d212016-04-06 10:51:14 -07006225 dwFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04006226 if (iRet >= 1 && resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
dsinclairf27aeec2016-06-07 19:36:18 -07006227 accessorValue->Assign(
6228 pScriptContext->GetJSValueFromMap(resoveNodeRS.nodes.GetAt(0)));
tsepezd19e9122016-11-02 15:43:18 -07006229 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04006230 }
tsepezd19e9122016-11-02 15:43:18 -07006231 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04006232}
dsinclair48d91dd2016-05-31 11:54:01 -07006233
6234// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006235int32_t CXFA_FM2JSContext::ResolveObjects(CFXJSE_Value* pThis,
6236 CFXJSE_Value* pRefValue,
Dan Sinclair1770c022016-03-14 14:14:16 -04006237 const CFX_ByteStringC& bsSomExp,
6238 XFA_RESOLVENODE_RS& resoveNodeRS,
tsepezd19e9122016-11-02 15:43:18 -07006239 bool bdotAccessor,
6240 bool bHasNoResolveName) {
dsinclair8f3074b2016-06-02 17:45:25 -07006241 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclairbd136fb2016-06-09 11:47:51 -07006242 if (!pDoc)
6243 return -1;
6244
6245 CFX_WideString wsSomExpression = CFX_WideString::FromUTF8(bsSomExp);
dsinclairdf4bc592016-03-31 20:34:43 -07006246 CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext();
dsinclair48d91dd2016-05-31 11:54:01 -07006247 CXFA_Object* pNode = nullptr;
tsepez736f28a2016-03-25 14:19:51 -07006248 uint32_t dFlags = 0UL;
Dan Sinclair1770c022016-03-14 14:14:16 -04006249 if (bdotAccessor) {
dsinclair769b1372016-06-08 13:12:41 -07006250 if (pRefValue && pRefValue->IsNull()) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006251 pNode = pScriptContext->GetThisObject();
6252 dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
6253 } else {
dsinclair8f3074b2016-06-02 17:45:25 -07006254 pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr);
dsinclair43854a52016-04-27 12:26:00 -07006255 ASSERT(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04006256 if (bHasNoResolveName) {
6257 CFX_WideString wsName;
dsinclairbd136fb2016-06-09 11:47:51 -07006258 if (CXFA_Node* pXFANode = pNode->AsNode())
tsepezd19e9122016-11-02 15:43:18 -07006259 pXFANode->GetAttribute(XFA_ATTRIBUTE_Name, wsName, false);
dsinclair017052a2016-06-28 07:43:51 -07006260 if (wsName.IsEmpty())
6261 wsName = FX_WSTRC(L"#") + pNode->GetClassName();
dsinclairbd136fb2016-06-09 11:47:51 -07006262
Dan Sinclair1770c022016-03-14 14:14:16 -04006263 wsSomExpression = wsName + wsSomExpression;
6264 dFlags = XFA_RESOLVENODE_Siblings;
6265 } else {
6266 dFlags = (bsSomExp == "*")
6267 ? (XFA_RESOLVENODE_Children)
6268 : (XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
6269 XFA_RESOLVENODE_Properties);
6270 }
6271 }
6272 } else {
dsinclair8f3074b2016-06-02 17:45:25 -07006273 pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04006274 dFlags = XFA_RESOLVENODE_AnyChild;
6275 }
dsinclairbd136fb2016-06-09 11:47:51 -07006276 return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringC(),
tsepezfc58ad12016-04-05 12:22:15 -07006277 resoveNodeRS, dFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04006278}
dsinclair48d91dd2016-05-31 11:54:01 -07006279
6280// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006281void CXFA_FM2JSContext::ParseResolveResult(
dsinclair12a6b0c2016-05-26 11:14:08 -07006282 CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04006283 const XFA_RESOLVENODE_RS& resoveNodeRS,
dsinclair12a6b0c2016-05-26 11:14:08 -07006284 CFXJSE_Value* pParentValue,
6285 CFXJSE_Value**& resultValues,
Dan Sinclair1770c022016-03-14 14:14:16 -04006286 int32_t& iSize,
tsepezd19e9122016-11-02 15:43:18 -07006287 bool& bAttribute) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006288 iSize = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07006289 resultValues = nullptr;
dsinclairbd136fb2016-06-09 11:47:51 -07006290
6291 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
6292 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04006293 if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
tsepezd19e9122016-11-02 15:43:18 -07006294 bAttribute = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04006295 iSize = resoveNodeRS.nodes.GetSize();
dsinclair12a6b0c2016-05-26 11:14:08 -07006296 resultValues = FX_Alloc(CFXJSE_Value*, iSize);
Dan Sinclair1770c022016-03-14 14:14:16 -04006297 for (int32_t i = 0; i < iSize; i++) {
dsinclair86fad992016-05-31 11:34:04 -07006298 resultValues[i] = new CFXJSE_Value(pIsolate);
dsinclairf27aeec2016-06-07 19:36:18 -07006299 resultValues[i]->Assign(
Dan Sinclair1770c022016-03-14 14:14:16 -04006300 pContext->GetDocument()->GetScriptContext()->GetJSValueFromMap(
6301 resoveNodeRS.nodes.GetAt(i)));
6302 }
dsinclairbd136fb2016-06-09 11:47:51 -07006303 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04006304 }
dsinclairbd136fb2016-06-09 11:47:51 -07006305
6306 CXFA_ValueArray objectProperties(pIsolate);
6307 int32_t iRet = resoveNodeRS.GetAttributeResult(objectProperties);
6308 bAttribute = (iRet == 0);
6309 if (!bAttribute) {
6310 iSize = iRet;
6311 resultValues = FX_Alloc(CFXJSE_Value*, iSize);
6312 for (int32_t i = 0; i < iSize; i++) {
6313 resultValues[i] = new CFXJSE_Value(pIsolate);
6314 resultValues[i]->Assign(objectProperties[i]);
6315 }
6316 return;
6317 }
6318
6319 if (!pParentValue || !pParentValue->IsObject())
6320 return;
6321
6322 iSize = 1;
6323 resultValues = FX_Alloc(CFXJSE_Value*, 1);
6324 resultValues[0] = new CFXJSE_Value(pIsolate);
6325 resultValues[0]->Assign(pParentValue);
Dan Sinclair1770c022016-03-14 14:14:16 -04006326}
dsinclair48d91dd2016-05-31 11:54:01 -07006327
6328// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006329int32_t CXFA_FM2JSContext::ValueToInteger(CFXJSE_Value* pThis,
6330 CFXJSE_Value* pValue) {
dsinclair769b1372016-06-08 13:12:41 -07006331 if (!pValue)
6332 return 0;
6333
dsinclair8f3074b2016-06-02 17:45:25 -07006334 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006335 if (pValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006336 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6337 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6338 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006339 pValue->GetObjectPropertyByIdx(1, propertyValue.get());
6340 pValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006341 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006342 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006343 return ValueToInteger(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006344 }
dsinclairbd136fb2016-06-09 11:47:51 -07006345
dsinclair2f5582f2016-06-09 11:48:23 -07006346 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006347 newPropertyValue.get());
6348 return ValueToInteger(pThis, newPropertyValue.get());
6349 }
6350 if (pValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006351 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6352 GetObjectDefaultValue(pValue, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006353 return ValueToInteger(pThis, newPropertyValue.get());
6354 }
dsinclair2f5582f2016-06-09 11:48:23 -07006355 if (pValue->IsString())
6356 return FXSYS_atoi(pValue->ToString().c_str());
dsinclairbd136fb2016-06-09 11:47:51 -07006357 return pValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006358}
dsinclair48d91dd2016-05-31 11:54:01 -07006359
6360// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006361FX_FLOAT CXFA_FM2JSContext::ValueToFloat(CFXJSE_Value* pThis,
6362 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006363 if (!arg)
6364 return 0.0f;
6365
dsinclair8f3074b2016-06-02 17:45:25 -07006366 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006367 if (arg->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006368 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6369 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6370 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006371 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6372 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006373 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006374 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006375 return ValueToFloat(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006376 }
dsinclair2f5582f2016-06-09 11:48:23 -07006377 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006378 newPropertyValue.get());
6379 return ValueToFloat(pThis, newPropertyValue.get());
6380 }
6381 if (arg->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006382 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6383 GetObjectDefaultValue(arg, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006384 return ValueToFloat(pThis, newPropertyValue.get());
6385 }
dsinclair2f5582f2016-06-09 11:48:23 -07006386 if (arg->IsString())
6387 return (FX_FLOAT)XFA_ByteStringToDouble(arg->ToString().AsStringC());
dsinclairbd136fb2016-06-09 11:47:51 -07006388 if (arg->IsUndefined())
6389 return 0;
6390
6391 return arg->ToFloat();
Dan Sinclair1770c022016-03-14 14:14:16 -04006392}
dsinclair48d91dd2016-05-31 11:54:01 -07006393
6394// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006395FX_DOUBLE CXFA_FM2JSContext::ValueToDouble(CFXJSE_Value* pThis,
6396 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006397 if (!arg)
6398 return 0;
6399
dsinclair8f3074b2016-06-02 17:45:25 -07006400 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006401 if (arg->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006402 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6403 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6404 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006405 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6406 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006407 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006408 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006409 return ValueToDouble(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006410 }
dsinclair2f5582f2016-06-09 11:48:23 -07006411 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006412 newPropertyValue.get());
6413 return ValueToDouble(pThis, newPropertyValue.get());
6414 }
6415 if (arg->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006416 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6417 GetObjectDefaultValue(arg, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006418 return ValueToDouble(pThis, newPropertyValue.get());
6419 }
dsinclair2f5582f2016-06-09 11:48:23 -07006420 if (arg->IsString())
6421 return XFA_ByteStringToDouble(arg->ToString().AsStringC());
dsinclairbd136fb2016-06-09 11:47:51 -07006422 if (arg->IsUndefined())
6423 return 0;
6424 return arg->ToDouble();
Dan Sinclair1770c022016-03-14 14:14:16 -04006425}
tsepez1c9cfe12016-05-26 13:30:56 -07006426
dsinclairdbdcb812016-06-01 20:07:22 -07006427// static.
6428double CXFA_FM2JSContext::ExtractDouble(CFXJSE_Value* pThis,
6429 CFXJSE_Value* src,
6430 bool* ret) {
6431 ASSERT(ret);
dsinclairdbdcb812016-06-01 20:07:22 -07006432 *ret = true;
6433
dsinclair769b1372016-06-08 13:12:41 -07006434 if (!src)
6435 return 0;
6436
dsinclairbd136fb2016-06-09 11:47:51 -07006437 if (!src->IsArray())
6438 return ValueToDouble(pThis, src);
dsinclairdbdcb812016-06-01 20:07:22 -07006439
dsinclairbd136fb2016-06-09 11:47:51 -07006440 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
6441 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
6442 src->GetObjectProperty("length", lengthValue.get());
6443 int32_t iLength = lengthValue->ToInteger();
6444 if (iLength <= 2) {
6445 *ret = false;
6446 return 0.0;
dsinclairdbdcb812016-06-01 20:07:22 -07006447 }
dsinclairbd136fb2016-06-09 11:47:51 -07006448
6449 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6450 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6451 src->GetObjectPropertyByIdx(1, propertyValue.get());
6452 src->GetObjectPropertyByIdx(2, jsObjectValue.get());
6453 if (propertyValue->IsNull())
6454 return ValueToDouble(pThis, jsObjectValue.get());
6455
dsinclairbd136fb2016-06-09 11:47:51 -07006456 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -07006457 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006458 newPropertyValue.get());
6459 return ValueToDouble(pThis, newPropertyValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -07006460}
6461
dsinclair48d91dd2016-05-31 11:54:01 -07006462// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006463void CXFA_FM2JSContext::ValueToUTF8String(CFXJSE_Value* arg,
6464 CFX_ByteString& szOutputString) {
dsinclair769b1372016-06-08 13:12:41 -07006465 if (!arg)
6466 return;
6467
dsinclair2f5582f2016-06-09 11:48:23 -07006468 if (arg->IsNull() || arg->IsUndefined())
Dan Sinclair1770c022016-03-14 14:14:16 -04006469 szOutputString = "";
dsinclair2f5582f2016-06-09 11:48:23 -07006470 else if (arg->IsBoolean())
dsinclairf27aeec2016-06-07 19:36:18 -07006471 szOutputString = arg->ToBoolean() ? "1" : "0";
dsinclair2f5582f2016-06-09 11:48:23 -07006472 else
6473 szOutputString = arg->ToString();
Dan Sinclair1770c022016-03-14 14:14:16 -04006474}
tsepez1c9cfe12016-05-26 13:30:56 -07006475
dsinclaire80e9f82016-06-01 06:10:04 -07006476// static.
6477int32_t CXFA_FM2JSContext::Translate(const CFX_WideStringC& wsFormcalc,
6478 CFX_WideTextBuf& wsJavascript,
6479 CFX_WideString& wsError) {
6480 if (wsFormcalc.IsEmpty()) {
6481 wsJavascript.Clear();
6482 wsError.clear();
6483 return 0;
6484 }
6485 int32_t status = 0;
6486 CXFA_FMProgram program;
6487 status = program.Init(wsFormcalc);
6488 if (status) {
6489 wsError = program.GetError().message;
6490 return status;
6491 }
6492 status = program.ParseProgram();
6493 if (status) {
6494 wsError = program.GetError().message;
6495 return status;
6496 }
6497 program.TranslateProgram(wsJavascript);
6498 return 0;
6499}
6500
dsinclair48d91dd2016-05-31 11:54:01 -07006501CXFA_FM2JSContext::CXFA_FM2JSContext(v8::Isolate* pScriptIsolate,
6502 CFXJSE_Context* pScriptContext,
6503 CXFA_Document* pDoc)
6504 : m_pIsolate(pScriptIsolate),
dsinclair769b1372016-06-08 13:12:41 -07006505 m_pFMClass(
6506 CFXJSE_Class::Create(pScriptContext, &formcalc_fm2js_descriptor)),
dsinclair48d91dd2016-05-31 11:54:01 -07006507 m_pValue(new CFXJSE_Value(pScriptIsolate)),
6508 m_pDocument(pDoc) {
dsinclairf27aeec2016-06-07 19:36:18 -07006509 m_pValue.get()->SetNull();
6510 m_pValue.get()->SetObject(this, m_pFMClass);
Dan Sinclair1770c022016-03-14 14:14:16 -04006511}
tsepez1c9cfe12016-05-26 13:30:56 -07006512
dsinclair48d91dd2016-05-31 11:54:01 -07006513CXFA_FM2JSContext::~CXFA_FM2JSContext() {}
6514
dsinclair12a6b0c2016-05-26 11:14:08 -07006515void CXFA_FM2JSContext::GlobalPropertyGetter(CFXJSE_Value* pValue) {
dsinclairf27aeec2016-06-07 19:36:18 -07006516 pValue->Assign(m_pValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006517}
tsepez5c4dd352016-05-26 13:57:58 -07006518
dsinclair2235b7b2016-06-02 07:42:25 -07006519void CXFA_FM2JSContext::ThrowException(int32_t iStringID, ...) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006520 IXFA_AppProvider* pAppProvider = m_pDocument->GetNotify()->GetAppProvider();
dsinclair43854a52016-04-27 12:26:00 -07006521 ASSERT(pAppProvider);
Dan Sinclair1770c022016-03-14 14:14:16 -04006522 CFX_WideString wsFormat;
6523 pAppProvider->LoadString(iStringID, wsFormat);
6524 CFX_WideString wsMessage;
6525 va_list arg_ptr;
6526 va_start(arg_ptr, iStringID);
tsepezbd9748d2016-04-13 21:40:19 -07006527 wsMessage.FormatV(wsFormat.c_str(), arg_ptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04006528 va_end(arg_ptr);
tsepez28f97ff2016-04-04 16:41:35 -07006529 FXJSE_ThrowMessage(
dsinclair769b1372016-06-08 13:12:41 -07006530 FX_UTF8Encode(wsMessage.c_str(), wsMessage.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04006531}