1 #include "jsi.h"
2 #include "jslex.h"
3 #include "jscompile.h"
4 #include "jsvalue.h"
5 #include "jsbuiltin.h"
6
jsB_globalf(js_State * J,const char * name,js_CFunction cfun,int n)7 static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
8 {
9 js_newcfunction(J, cfun, name, n);
10 js_defglobal(J, name, JS_DONTENUM);
11 }
12
jsB_propf(js_State * J,const char * name,js_CFunction cfun,int n)13 void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n)
14 {
15 const char *pname = strrchr(name, '.');
16 pname = pname ? pname + 1 : name;
17 js_newcfunction(J, cfun, name, n);
18 js_defproperty(J, -2, pname, JS_DONTENUM);
19 }
20
jsB_propn(js_State * J,const char * name,double number)21 void jsB_propn(js_State *J, const char *name, double number)
22 {
23 js_pushnumber(J, number);
24 js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF);
25 }
26
jsB_props(js_State * J,const char * name,const char * string)27 void jsB_props(js_State *J, const char *name, const char *string)
28 {
29 js_pushliteral(J, string);
30 js_defproperty(J, -2, name, JS_DONTENUM);
31 }
32
jsB_parseInt(js_State * J)33 static void jsB_parseInt(js_State *J)
34 {
35 const char *s = js_tostring(J, 1);
36 int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 10;
37 double sign = 1;
38 double n;
39 char *e;
40
41 while (jsY_iswhite(*s) || jsY_isnewline(*s))
42 ++s;
43 if (*s == '-') {
44 ++s;
45 sign = -1;
46 } else if (*s == '+') {
47 ++s;
48 }
49 if (radix == 0) {
50 radix = 10;
51 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
52 s += 2;
53 radix = 16;
54 }
55 } else if (radix < 2 || radix > 36) {
56 js_pushnumber(J, NAN);
57 return;
58 }
59 n = strtol(s, &e, radix);
60 if (s == e)
61 js_pushnumber(J, NAN);
62 else
63 js_pushnumber(J, n * sign);
64 }
65
jsB_parseFloat(js_State * J)66 static void jsB_parseFloat(js_State *J)
67 {
68 const char *s = js_tostring(J, 1);
69 char *e;
70 double n;
71
72 while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
73 if (!strncmp(s, "Infinity", 8))
74 js_pushnumber(J, INFINITY);
75 else if (!strncmp(s, "+Infinity", 9))
76 js_pushnumber(J, INFINITY);
77 else if (!strncmp(s, "-Infinity", 9))
78 js_pushnumber(J, -INFINITY);
79 else {
80 n = js_stringtofloat(s, &e);
81 if (e == s)
82 js_pushnumber(J, NAN);
83 else
84 js_pushnumber(J, n);
85 }
86 }
87
jsB_isNaN(js_State * J)88 static void jsB_isNaN(js_State *J)
89 {
90 double n = js_tonumber(J, 1);
91 js_pushboolean(J, isnan(n));
92 }
93
jsB_isFinite(js_State * J)94 static void jsB_isFinite(js_State *J)
95 {
96 double n = js_tonumber(J, 1);
97 js_pushboolean(J, isfinite(n));
98 }
99
Encode(js_State * J,const char * str,const char * unescaped)100 static void Encode(js_State *J, const char *str, const char *unescaped)
101 {
102 js_Buffer *sb = NULL;
103
104 static const char *HEX = "0123456789ABCDEF";
105
106 if (js_try(J)) {
107 js_free(J, sb);
108 js_throw(J);
109 }
110
111 while (*str) {
112 int c = (unsigned char) *str++;
113 if (strchr(unescaped, c))
114 js_putc(J, &sb, c);
115 else {
116 js_putc(J, &sb, '%');
117 js_putc(J, &sb, HEX[(c >> 4) & 0xf]);
118 js_putc(J, &sb, HEX[c & 0xf]);
119 }
120 }
121 js_putc(J, &sb, 0);
122
123 js_pushstring(J, sb ? sb->s : "");
124 js_endtry(J);
125 js_free(J, sb);
126 }
127
Decode(js_State * J,const char * str,const char * reserved)128 static void Decode(js_State *J, const char *str, const char *reserved)
129 {
130 js_Buffer *sb = NULL;
131 int a, b;
132
133 if (js_try(J)) {
134 js_free(J, sb);
135 js_throw(J);
136 }
137
138 while (*str) {
139 int c = (unsigned char) *str++;
140 if (c != '%')
141 js_putc(J, &sb, c);
142 else {
143 if (!str[0] || !str[1])
144 js_urierror(J, "truncated escape sequence");
145 a = *str++;
146 b = *str++;
147 if (!jsY_ishex(a) || !jsY_ishex(b))
148 js_urierror(J, "invalid escape sequence");
149 c = jsY_tohex(a) << 4 | jsY_tohex(b);
150 if (!strchr(reserved, c))
151 js_putc(J, &sb, c);
152 else {
153 js_putc(J, &sb, '%');
154 js_putc(J, &sb, a);
155 js_putc(J, &sb, b);
156 }
157 }
158 }
159 js_putc(J, &sb, 0);
160
161 js_pushstring(J, sb ? sb->s : "");
162 js_endtry(J);
163 js_free(J, sb);
164 }
165
166 #define URIRESERVED ";/?:@&=+$,"
167 #define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
168 #define URIDIGIT "0123456789"
169 #define URIMARK "-_.!~*`()"
170 #define URIUNESCAPED URIALPHA URIDIGIT URIMARK
171
jsB_decodeURI(js_State * J)172 static void jsB_decodeURI(js_State *J)
173 {
174 Decode(J, js_tostring(J, 1), URIRESERVED "#");
175 }
176
jsB_decodeURIComponent(js_State * J)177 static void jsB_decodeURIComponent(js_State *J)
178 {
179 Decode(J, js_tostring(J, 1), "");
180 }
181
jsB_encodeURI(js_State * J)182 static void jsB_encodeURI(js_State *J)
183 {
184 Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
185 }
186
jsB_encodeURIComponent(js_State * J)187 static void jsB_encodeURIComponent(js_State *J)
188 {
189 Encode(J, js_tostring(J, 1), URIUNESCAPED);
190 }
191
jsB_init(js_State * J)192 void jsB_init(js_State *J)
193 {
194 /* Create the prototype objects here, before the constructors */
195 J->Object_prototype = jsV_newobject(J, JS_COBJECT, NULL);
196 J->Array_prototype = jsV_newobject(J, JS_CARRAY, J->Object_prototype);
197 J->Function_prototype = jsV_newobject(J, JS_CCFUNCTION, J->Object_prototype);
198 J->Boolean_prototype = jsV_newobject(J, JS_CBOOLEAN, J->Object_prototype);
199 J->Number_prototype = jsV_newobject(J, JS_CNUMBER, J->Object_prototype);
200 J->String_prototype = jsV_newobject(J, JS_CSTRING, J->Object_prototype);
201 J->RegExp_prototype = jsV_newobject(J, JS_COBJECT, J->Object_prototype);
202 J->Date_prototype = jsV_newobject(J, JS_CDATE, J->Object_prototype);
203
204 /* All the native error types */
205 J->Error_prototype = jsV_newobject(J, JS_CERROR, J->Object_prototype);
206 J->EvalError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
207 J->RangeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
208 J->ReferenceError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
209 J->SyntaxError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
210 J->TypeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
211 J->URIError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
212
213 /* Create the constructors and fill out the prototype objects */
214 jsB_initobject(J);
215 jsB_initarray(J);
216 jsB_initfunction(J);
217 jsB_initboolean(J);
218 jsB_initnumber(J);
219 jsB_initstring(J);
220 jsB_initregexp(J);
221 jsB_initdate(J);
222 jsB_initerror(J);
223 jsB_initmath(J);
224 jsB_initjson(J);
225
226 /* Initialize the global object */
227 js_pushnumber(J, NAN);
228 js_defglobal(J, "NaN", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
229
230 js_pushnumber(J, INFINITY);
231 js_defglobal(J, "Infinity", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
232
233 js_pushundefined(J);
234 js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
235
236 jsB_globalf(J, "parseInt", jsB_parseInt, 1);
237 jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
238 jsB_globalf(J, "isNaN", jsB_isNaN, 1);
239 jsB_globalf(J, "isFinite", jsB_isFinite, 1);
240
241 jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
242 jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
243 jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
244 jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
245 }
246