1 | #include "jsi.h" |
2 | #include "jsvalue.h" |
3 | #include "jsbuiltin.h" |
4 | #include "utf.h" |
5 | #include "regexp.h" |
6 | |
7 | static int js_doregexec(js_State *J, Reprog *prog, const char *string, Resub *sub, int eflags) |
8 | { |
9 | int result = js_regexec(prog, string, sub, eflags); |
10 | if (result < 0) |
11 | js_error(J, "regexec failed" ); |
12 | return result; |
13 | } |
14 | |
15 | static const char *checkstring(js_State *J, int idx) |
16 | { |
17 | if (!js_iscoercible(J, idx)) |
18 | js_typeerror(J, "string function called on null or undefined" ); |
19 | return js_tostring(J, idx); |
20 | } |
21 | |
22 | int js_runeat(js_State *J, const char *s, int i) |
23 | { |
24 | Rune rune = 0; |
25 | while (i-- >= 0) { |
26 | rune = *(unsigned char*)s; |
27 | if (rune < Runeself) { |
28 | if (rune == 0) |
29 | return 0; |
30 | ++s; |
31 | } else |
32 | s += chartorune(&rune, s); |
33 | } |
34 | return rune; |
35 | } |
36 | |
37 | const char *js_utfidxtoptr(const char *s, int i) |
38 | { |
39 | Rune rune; |
40 | while (i-- > 0) { |
41 | rune = *(unsigned char*)s; |
42 | if (rune < Runeself) { |
43 | if (rune == 0) |
44 | return NULL; |
45 | ++s; |
46 | } else |
47 | s += chartorune(&rune, s); |
48 | } |
49 | return s; |
50 | } |
51 | |
52 | int js_utfptrtoidx(const char *s, const char *p) |
53 | { |
54 | Rune rune; |
55 | int i = 0; |
56 | while (s < p) { |
57 | if (*(unsigned char *)s < Runeself) |
58 | ++s; |
59 | else |
60 | s += chartorune(&rune, s); |
61 | ++i; |
62 | } |
63 | return i; |
64 | } |
65 | |
66 | static void jsB_new_String(js_State *J) |
67 | { |
68 | js_newstring(J, js_gettop(J) > 1 ? js_tostring(J, 1) : "" ); |
69 | } |
70 | |
71 | static void jsB_String(js_State *J) |
72 | { |
73 | js_pushstring(J, js_gettop(J) > 1 ? js_tostring(J, 1) : "" ); |
74 | } |
75 | |
76 | static void Sp_toString(js_State *J) |
77 | { |
78 | js_Object *self = js_toobject(J, 0); |
79 | if (self->type != JS_CSTRING) js_typeerror(J, "not a string" ); |
80 | js_pushliteral(J, self->u.s.string); |
81 | } |
82 | |
83 | static void Sp_valueOf(js_State *J) |
84 | { |
85 | js_Object *self = js_toobject(J, 0); |
86 | if (self->type != JS_CSTRING) js_typeerror(J, "not a string" ); |
87 | js_pushliteral(J, self->u.s.string); |
88 | } |
89 | |
90 | static void Sp_charAt(js_State *J) |
91 | { |
92 | char buf[UTFmax + 1]; |
93 | const char *s = checkstring(J, 0); |
94 | int pos = js_tointeger(J, 1); |
95 | Rune rune = js_runeat(J, s, pos); |
96 | if (rune > 0) { |
97 | buf[runetochar(buf, &rune)] = 0; |
98 | js_pushstring(J, buf); |
99 | } else { |
100 | js_pushliteral(J, "" ); |
101 | } |
102 | } |
103 | |
104 | static void Sp_charCodeAt(js_State *J) |
105 | { |
106 | const char *s = checkstring(J, 0); |
107 | int pos = js_tointeger(J, 1); |
108 | Rune rune = js_runeat(J, s, pos); |
109 | if (rune > 0) |
110 | js_pushnumber(J, rune); |
111 | else |
112 | js_pushnumber(J, NAN); |
113 | } |
114 | |
115 | static void Sp_concat(js_State *J) |
116 | { |
117 | int i, top = js_gettop(J); |
118 | int n; |
119 | char * volatile out; |
120 | const char *s; |
121 | |
122 | if (top == 1) |
123 | return; |
124 | |
125 | s = checkstring(J, 0); |
126 | n = strlen(s); |
127 | out = js_malloc(J, n + 1); |
128 | strcpy(out, s); |
129 | |
130 | if (js_try(J)) { |
131 | js_free(J, out); |
132 | js_throw(J); |
133 | } |
134 | |
135 | for (i = 1; i < top; ++i) { |
136 | s = js_tostring(J, i); |
137 | n += strlen(s); |
138 | out = js_realloc(J, out, n + 1); |
139 | strcat(out, s); |
140 | } |
141 | |
142 | js_pushstring(J, out); |
143 | js_endtry(J); |
144 | js_free(J, out); |
145 | } |
146 | |
147 | static void Sp_indexOf(js_State *J) |
148 | { |
149 | const char *haystack = checkstring(J, 0); |
150 | const char *needle = js_tostring(J, 1); |
151 | int pos = js_tointeger(J, 2); |
152 | int len = strlen(needle); |
153 | int k = 0; |
154 | Rune rune; |
155 | while (*haystack) { |
156 | if (k >= pos && !strncmp(haystack, needle, len)) { |
157 | js_pushnumber(J, k); |
158 | return; |
159 | } |
160 | haystack += chartorune(&rune, haystack); |
161 | ++k; |
162 | } |
163 | js_pushnumber(J, -1); |
164 | } |
165 | |
166 | static void Sp_lastIndexOf(js_State *J) |
167 | { |
168 | const char *haystack = checkstring(J, 0); |
169 | const char *needle = js_tostring(J, 1); |
170 | int pos = js_isdefined(J, 2) ? js_tointeger(J, 2) : (int)strlen(haystack); |
171 | int len = strlen(needle); |
172 | int k = 0, last = -1; |
173 | Rune rune; |
174 | while (*haystack && k <= pos) { |
175 | if (!strncmp(haystack, needle, len)) |
176 | last = k; |
177 | haystack += chartorune(&rune, haystack); |
178 | ++k; |
179 | } |
180 | js_pushnumber(J, last); |
181 | } |
182 | |
183 | static void Sp_localeCompare(js_State *J) |
184 | { |
185 | const char *a = checkstring(J, 0); |
186 | const char *b = js_tostring(J, 1); |
187 | js_pushnumber(J, strcmp(a, b)); |
188 | } |
189 | |
190 | static void Sp_slice(js_State *J) |
191 | { |
192 | const char *str = checkstring(J, 0); |
193 | const char *ss, *ee; |
194 | int len = utflen(str); |
195 | int s = js_tointeger(J, 1); |
196 | int e = js_isdefined(J, 2) ? js_tointeger(J, 2) : len; |
197 | |
198 | s = s < 0 ? s + len : s; |
199 | e = e < 0 ? e + len : e; |
200 | |
201 | s = s < 0 ? 0 : s > len ? len : s; |
202 | e = e < 0 ? 0 : e > len ? len : e; |
203 | |
204 | if (s < e) { |
205 | ss = js_utfidxtoptr(str, s); |
206 | ee = js_utfidxtoptr(ss, e - s); |
207 | } else { |
208 | ss = js_utfidxtoptr(str, e); |
209 | ee = js_utfidxtoptr(ss, s - e); |
210 | } |
211 | |
212 | js_pushlstring(J, ss, ee - ss); |
213 | } |
214 | |
215 | static void Sp_substring(js_State *J) |
216 | { |
217 | const char *str = checkstring(J, 0); |
218 | const char *ss, *ee; |
219 | int len = utflen(str); |
220 | int s = js_tointeger(J, 1); |
221 | int e = js_isdefined(J, 2) ? js_tointeger(J, 2) : len; |
222 | |
223 | s = s < 0 ? 0 : s > len ? len : s; |
224 | e = e < 0 ? 0 : e > len ? len : e; |
225 | |
226 | if (s < e) { |
227 | ss = js_utfidxtoptr(str, s); |
228 | ee = js_utfidxtoptr(ss, e - s); |
229 | } else { |
230 | ss = js_utfidxtoptr(str, e); |
231 | ee = js_utfidxtoptr(ss, s - e); |
232 | } |
233 | |
234 | js_pushlstring(J, ss, ee - ss); |
235 | } |
236 | |
237 | static void Sp_toLowerCase(js_State *J) |
238 | { |
239 | const char *src = checkstring(J, 0); |
240 | char *dst = js_malloc(J, UTFmax * strlen(src) + 1); |
241 | const char *s = src; |
242 | char *d = dst; |
243 | Rune rune; |
244 | while (*s) { |
245 | s += chartorune(&rune, s); |
246 | rune = tolowerrune(rune); |
247 | d += runetochar(d, &rune); |
248 | } |
249 | *d = 0; |
250 | if (js_try(J)) { |
251 | js_free(J, dst); |
252 | js_throw(J); |
253 | } |
254 | js_pushstring(J, dst); |
255 | js_endtry(J); |
256 | js_free(J, dst); |
257 | } |
258 | |
259 | static void Sp_toUpperCase(js_State *J) |
260 | { |
261 | const char *src = checkstring(J, 0); |
262 | char *dst = js_malloc(J, UTFmax * strlen(src) + 1); |
263 | const char *s = src; |
264 | char *d = dst; |
265 | Rune rune; |
266 | while (*s) { |
267 | s += chartorune(&rune, s); |
268 | rune = toupperrune(rune); |
269 | d += runetochar(d, &rune); |
270 | } |
271 | *d = 0; |
272 | if (js_try(J)) { |
273 | js_free(J, dst); |
274 | js_throw(J); |
275 | } |
276 | js_pushstring(J, dst); |
277 | js_endtry(J); |
278 | js_free(J, dst); |
279 | } |
280 | |
281 | static int istrim(int c) |
282 | { |
283 | return c == 0x9 || c == 0xB || c == 0xC || c == 0x20 || c == 0xA0 || c == 0xFEFF || |
284 | c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029; |
285 | } |
286 | |
287 | static void Sp_trim(js_State *J) |
288 | { |
289 | const char *s, *e; |
290 | s = checkstring(J, 0); |
291 | while (istrim(*s)) |
292 | ++s; |
293 | e = s + strlen(s); |
294 | while (e > s && istrim(e[-1])) |
295 | --e; |
296 | js_pushlstring(J, s, e - s); |
297 | } |
298 | |
299 | static void S_fromCharCode(js_State *J) |
300 | { |
301 | int i, top = js_gettop(J); |
302 | Rune c; |
303 | char *s, *p; |
304 | |
305 | s = p = js_malloc(J, (top-1) * UTFmax + 1); |
306 | |
307 | if (js_try(J)) { |
308 | js_free(J, s); |
309 | js_throw(J); |
310 | } |
311 | |
312 | for (i = 1; i < top; ++i) { |
313 | c = js_touint16(J, i); |
314 | p += runetochar(p, &c); |
315 | } |
316 | *p = 0; |
317 | js_pushstring(J, s); |
318 | |
319 | js_endtry(J); |
320 | js_free(J, s); |
321 | } |
322 | |
323 | static void Sp_match(js_State *J) |
324 | { |
325 | js_Regexp *re; |
326 | const char *text; |
327 | int len; |
328 | const char *a, *b, *c, *e; |
329 | Resub m; |
330 | |
331 | text = checkstring(J, 0); |
332 | |
333 | if (js_isregexp(J, 1)) |
334 | js_copy(J, 1); |
335 | else if (js_isundefined(J, 1)) |
336 | js_newregexp(J, "" , 0); |
337 | else |
338 | js_newregexp(J, js_tostring(J, 1), 0); |
339 | |
340 | re = js_toregexp(J, -1); |
341 | if (!(re->flags & JS_REGEXP_G)) { |
342 | js_RegExp_prototype_exec(J, re, text); |
343 | return; |
344 | } |
345 | |
346 | re->last = 0; |
347 | |
348 | js_newarray(J); |
349 | |
350 | len = 0; |
351 | a = text; |
352 | e = text + strlen(text); |
353 | while (a <= e) { |
354 | if (js_doregexec(J, re->prog, a, &m, a > text ? REG_NOTBOL : 0)) |
355 | break; |
356 | |
357 | b = m.sub[0].sp; |
358 | c = m.sub[0].ep; |
359 | |
360 | js_pushlstring(J, b, c - b); |
361 | js_setindex(J, -2, len++); |
362 | |
363 | a = c; |
364 | if (c - b == 0) |
365 | ++a; |
366 | } |
367 | |
368 | if (len == 0) { |
369 | js_pop(J, 1); |
370 | js_pushnull(J); |
371 | } |
372 | } |
373 | |
374 | static void Sp_search(js_State *J) |
375 | { |
376 | js_Regexp *re; |
377 | const char *text; |
378 | Resub m; |
379 | |
380 | text = checkstring(J, 0); |
381 | |
382 | if (js_isregexp(J, 1)) |
383 | js_copy(J, 1); |
384 | else if (js_isundefined(J, 1)) |
385 | js_newregexp(J, "" , 0); |
386 | else |
387 | js_newregexp(J, js_tostring(J, 1), 0); |
388 | |
389 | re = js_toregexp(J, -1); |
390 | |
391 | if (!js_doregexec(J, re->prog, text, &m, 0)) |
392 | js_pushnumber(J, js_utfptrtoidx(text, m.sub[0].sp)); |
393 | else |
394 | js_pushnumber(J, -1); |
395 | } |
396 | |
397 | static void Sp_replace_regexp(js_State *J) |
398 | { |
399 | js_Regexp *re; |
400 | const char *source, *s, *r; |
401 | js_Buffer *sb = NULL; |
402 | int n, x; |
403 | Resub m; |
404 | |
405 | source = checkstring(J, 0); |
406 | re = js_toregexp(J, 1); |
407 | |
408 | if (js_doregexec(J, re->prog, source, &m, 0)) { |
409 | js_copy(J, 0); |
410 | return; |
411 | } |
412 | |
413 | re->last = 0; |
414 | |
415 | loop: |
416 | s = m.sub[0].sp; |
417 | n = m.sub[0].ep - m.sub[0].sp; |
418 | |
419 | if (js_iscallable(J, 2)) { |
420 | js_copy(J, 2); |
421 | js_pushundefined(J); |
422 | for (x = 0; m.sub[x].sp; ++x) /* arg 0..x: substring and subexps that matched */ |
423 | js_pushlstring(J, m.sub[x].sp, m.sub[x].ep - m.sub[x].sp); |
424 | js_pushnumber(J, s - source); /* arg x+2: offset within search string */ |
425 | js_copy(J, 0); /* arg x+3: search string */ |
426 | js_call(J, 2 + x); |
427 | r = js_tostring(J, -1); |
428 | js_putm(J, &sb, source, s); |
429 | js_puts(J, &sb, r); |
430 | js_pop(J, 1); |
431 | } else { |
432 | r = js_tostring(J, 2); |
433 | js_putm(J, &sb, source, s); |
434 | while (*r) { |
435 | if (*r == '$') { |
436 | switch (*(++r)) { |
437 | case 0: --r; /* end of string; back up */ |
438 | /* fallthrough */ |
439 | case '$': js_putc(J, &sb, '$'); break; |
440 | case '`': js_putm(J, &sb, source, s); break; |
441 | case '\'': js_puts(J, &sb, s + n); break; |
442 | case '&': |
443 | js_putm(J, &sb, s, s + n); |
444 | break; |
445 | case '0': case '1': case '2': case '3': case '4': |
446 | case '5': case '6': case '7': case '8': case '9': |
447 | x = *r - '0'; |
448 | if (r[1] >= '0' && r[1] <= '9') |
449 | x = x * 10 + *(++r) - '0'; |
450 | if (x > 0 && x < m.nsub) { |
451 | js_putm(J, &sb, m.sub[x].sp, m.sub[x].ep); |
452 | } else { |
453 | js_putc(J, &sb, '$'); |
454 | if (x > 10) { |
455 | js_putc(J, &sb, '0' + x / 10); |
456 | js_putc(J, &sb, '0' + x % 10); |
457 | } else { |
458 | js_putc(J, &sb, '0' + x); |
459 | } |
460 | } |
461 | break; |
462 | default: |
463 | js_putc(J, &sb, '$'); |
464 | js_putc(J, &sb, *r); |
465 | break; |
466 | } |
467 | ++r; |
468 | } else { |
469 | js_putc(J, &sb, *r++); |
470 | } |
471 | } |
472 | } |
473 | |
474 | if (re->flags & JS_REGEXP_G) { |
475 | source = m.sub[0].ep; |
476 | if (n == 0) { |
477 | if (*source) |
478 | js_putc(J, &sb, *source++); |
479 | else |
480 | goto end; |
481 | } |
482 | if (!js_doregexec(J, re->prog, source, &m, REG_NOTBOL)) |
483 | goto loop; |
484 | } |
485 | |
486 | end: |
487 | js_puts(J, &sb, s + n); |
488 | js_putc(J, &sb, 0); |
489 | |
490 | if (js_try(J)) { |
491 | js_free(J, sb); |
492 | js_throw(J); |
493 | } |
494 | js_pushstring(J, sb ? sb->s : "" ); |
495 | js_endtry(J); |
496 | js_free(J, sb); |
497 | } |
498 | |
499 | static void Sp_replace_string(js_State *J) |
500 | { |
501 | const char *source, *needle, *s, *r; |
502 | js_Buffer *sb = NULL; |
503 | int n; |
504 | |
505 | source = checkstring(J, 0); |
506 | needle = js_tostring(J, 1); |
507 | |
508 | s = strstr(source, needle); |
509 | if (!s) { |
510 | js_copy(J, 0); |
511 | return; |
512 | } |
513 | n = strlen(needle); |
514 | |
515 | if (js_iscallable(J, 2)) { |
516 | js_copy(J, 2); |
517 | js_pushundefined(J); |
518 | js_pushlstring(J, s, n); /* arg 1: substring that matched */ |
519 | js_pushnumber(J, s - source); /* arg 2: offset within search string */ |
520 | js_copy(J, 0); /* arg 3: search string */ |
521 | js_call(J, 3); |
522 | r = js_tostring(J, -1); |
523 | js_putm(J, &sb, source, s); |
524 | js_puts(J, &sb, r); |
525 | js_puts(J, &sb, s + n); |
526 | js_putc(J, &sb, 0); |
527 | js_pop(J, 1); |
528 | } else { |
529 | r = js_tostring(J, 2); |
530 | js_putm(J, &sb, source, s); |
531 | while (*r) { |
532 | if (*r == '$') { |
533 | switch (*(++r)) { |
534 | case 0: --r; /* end of string; back up */ |
535 | /* fallthrough */ |
536 | case '$': js_putc(J, &sb, '$'); break; |
537 | case '&': js_putm(J, &sb, s, s + n); break; |
538 | case '`': js_putm(J, &sb, source, s); break; |
539 | case '\'': js_puts(J, &sb, s + n); break; |
540 | default: js_putc(J, &sb, '$'); js_putc(J, &sb, *r); break; |
541 | } |
542 | ++r; |
543 | } else { |
544 | js_putc(J, &sb, *r++); |
545 | } |
546 | } |
547 | js_puts(J, &sb, s + n); |
548 | js_putc(J, &sb, 0); |
549 | } |
550 | |
551 | if (js_try(J)) { |
552 | js_free(J, sb); |
553 | js_throw(J); |
554 | } |
555 | js_pushstring(J, sb ? sb->s : "" ); |
556 | js_endtry(J); |
557 | js_free(J, sb); |
558 | } |
559 | |
560 | static void Sp_replace(js_State *J) |
561 | { |
562 | if (js_isregexp(J, 1)) |
563 | Sp_replace_regexp(J); |
564 | else |
565 | Sp_replace_string(J); |
566 | } |
567 | |
568 | static void Sp_split_regexp(js_State *J) |
569 | { |
570 | js_Regexp *re; |
571 | const char *text; |
572 | int limit, len, k; |
573 | const char *p, *a, *b, *c, *e; |
574 | Resub m; |
575 | |
576 | text = checkstring(J, 0); |
577 | re = js_toregexp(J, 1); |
578 | limit = js_isdefined(J, 2) ? js_tointeger(J, 2) : 1 << 30; |
579 | |
580 | js_newarray(J); |
581 | len = 0; |
582 | |
583 | e = text + strlen(text); |
584 | |
585 | /* splitting the empty string */ |
586 | if (e == text) { |
587 | if (js_doregexec(J, re->prog, text, &m, 0)) { |
588 | if (len == limit) return; |
589 | js_pushliteral(J, "" ); |
590 | js_setindex(J, -2, 0); |
591 | } |
592 | return; |
593 | } |
594 | |
595 | p = a = text; |
596 | while (a < e) { |
597 | if (js_doregexec(J, re->prog, a, &m, a > text ? REG_NOTBOL : 0)) |
598 | break; /* no match */ |
599 | |
600 | b = m.sub[0].sp; |
601 | c = m.sub[0].ep; |
602 | |
603 | /* empty string at end of last match */ |
604 | if (b == p) { |
605 | ++a; |
606 | continue; |
607 | } |
608 | |
609 | if (len == limit) return; |
610 | js_pushlstring(J, p, b - p); |
611 | js_setindex(J, -2, len++); |
612 | |
613 | for (k = 1; k < m.nsub; ++k) { |
614 | if (len == limit) return; |
615 | js_pushlstring(J, m.sub[k].sp, m.sub[k].ep - m.sub[k].sp); |
616 | js_setindex(J, -2, len++); |
617 | } |
618 | |
619 | a = p = c; |
620 | } |
621 | |
622 | if (len == limit) return; |
623 | js_pushstring(J, p); |
624 | js_setindex(J, -2, len); |
625 | } |
626 | |
627 | static void Sp_split_string(js_State *J) |
628 | { |
629 | const char *str = checkstring(J, 0); |
630 | const char *sep = js_tostring(J, 1); |
631 | int limit = js_isdefined(J, 2) ? js_tointeger(J, 2) : 1 << 30; |
632 | int i, n; |
633 | |
634 | js_newarray(J); |
635 | |
636 | n = strlen(sep); |
637 | |
638 | /* empty string */ |
639 | if (n == 0) { |
640 | Rune rune; |
641 | for (i = 0; *str && i < limit; ++i) { |
642 | n = chartorune(&rune, str); |
643 | js_pushlstring(J, str, n); |
644 | js_setindex(J, -2, i); |
645 | str += n; |
646 | } |
647 | return; |
648 | } |
649 | |
650 | for (i = 0; str && i < limit; ++i) { |
651 | const char *s = strstr(str, sep); |
652 | if (s) { |
653 | js_pushlstring(J, str, s-str); |
654 | js_setindex(J, -2, i); |
655 | str = s + n; |
656 | } else { |
657 | js_pushstring(J, str); |
658 | js_setindex(J, -2, i); |
659 | str = NULL; |
660 | } |
661 | } |
662 | } |
663 | |
664 | static void Sp_split(js_State *J) |
665 | { |
666 | if (js_isundefined(J, 1)) { |
667 | js_newarray(J); |
668 | js_copy(J, 0); |
669 | js_setindex(J, -2, 0); |
670 | } else if (js_isregexp(J, 1)) { |
671 | Sp_split_regexp(J); |
672 | } else { |
673 | Sp_split_string(J); |
674 | } |
675 | } |
676 | |
677 | void jsB_initstring(js_State *J) |
678 | { |
679 | J->String_prototype->u.s.string = "" ; |
680 | J->String_prototype->u.s.length = 0; |
681 | |
682 | js_pushobject(J, J->String_prototype); |
683 | { |
684 | jsB_propf(J, "String.prototype.toString" , Sp_toString, 0); |
685 | jsB_propf(J, "String.prototype.valueOf" , Sp_valueOf, 0); |
686 | jsB_propf(J, "String.prototype.charAt" , Sp_charAt, 1); |
687 | jsB_propf(J, "String.prototype.charCodeAt" , Sp_charCodeAt, 1); |
688 | jsB_propf(J, "String.prototype.concat" , Sp_concat, 0); /* 1 */ |
689 | jsB_propf(J, "String.prototype.indexOf" , Sp_indexOf, 1); |
690 | jsB_propf(J, "String.prototype.lastIndexOf" , Sp_lastIndexOf, 1); |
691 | jsB_propf(J, "String.prototype.localeCompare" , Sp_localeCompare, 1); |
692 | jsB_propf(J, "String.prototype.match" , Sp_match, 1); |
693 | jsB_propf(J, "String.prototype.replace" , Sp_replace, 2); |
694 | jsB_propf(J, "String.prototype.search" , Sp_search, 1); |
695 | jsB_propf(J, "String.prototype.slice" , Sp_slice, 2); |
696 | jsB_propf(J, "String.prototype.split" , Sp_split, 2); |
697 | jsB_propf(J, "String.prototype.substring" , Sp_substring, 2); |
698 | jsB_propf(J, "String.prototype.toLowerCase" , Sp_toLowerCase, 0); |
699 | jsB_propf(J, "String.prototype.toLocaleLowerCase" , Sp_toLowerCase, 0); |
700 | jsB_propf(J, "String.prototype.toUpperCase" , Sp_toUpperCase, 0); |
701 | jsB_propf(J, "String.prototype.toLocaleUpperCase" , Sp_toUpperCase, 0); |
702 | |
703 | /* ES5 */ |
704 | jsB_propf(J, "String.prototype.trim" , Sp_trim, 0); |
705 | } |
706 | js_newcconstructor(J, jsB_String, jsB_new_String, "String" , 0); /* 1 */ |
707 | { |
708 | jsB_propf(J, "String.fromCharCode" , S_fromCharCode, 0); /* 1 */ |
709 | } |
710 | js_defglobal(J, "String" , JS_DONTENUM); |
711 | } |
712 | |