OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 26 matching lines...) Expand all Loading... |
37 var value = %_ArgumentsLength() == 0 ? '' : ToString(x); | 37 var value = %_ArgumentsLength() == 0 ? '' : ToString(x); |
38 if (%IsConstructCall()) { | 38 if (%IsConstructCall()) { |
39 %_SetValueOf(this, value); | 39 %_SetValueOf(this, value); |
40 } else { | 40 } else { |
41 return value; | 41 return value; |
42 } | 42 } |
43 }); | 43 }); |
44 | 44 |
45 %FunctionSetPrototype($String, new $String()); | 45 %FunctionSetPrototype($String, new $String()); |
46 | 46 |
47 %AddProperty($String.prototype, "constructor", $String, DONT_ENUM); | 47 // ECMA-262 section 15.5.4.2 |
| 48 function StringToString() { |
| 49 if (!IS_STRING(this) && %ClassOf(this) !== 'String') |
| 50 throw new $TypeError('String.prototype.toString is not generic'); |
| 51 return %_ValueOf(this); |
| 52 } |
48 | 53 |
49 %AddProperty($String.prototype, "valueOf", function valueOf() { | 54 |
| 55 // ECMA-262 section 15.5.4.3 |
| 56 function StringValueOf() { |
50 if (!IS_STRING(this) && %ClassOf(this) !== 'String') | 57 if (!IS_STRING(this) && %ClassOf(this) !== 'String') |
51 throw new $TypeError('String.prototype.valueOf is not generic'); | 58 throw new $TypeError('String.prototype.valueOf is not generic'); |
52 return %_ValueOf(this); | 59 return %_ValueOf(this); |
53 }, DONT_ENUM); | 60 } |
54 | 61 |
55 %AddProperty($String.prototype, "toString", function toString() { | 62 |
56 if (!IS_STRING(this) && %ClassOf(this) !== 'String') | 63 // ECMA-262, section 15.5.4.4 |
57 throw new $TypeError('String.prototype.toString is not generic'); | 64 function StringCharAt(pos) { |
58 return %_ValueOf(this); | 65 var subject = ToString(this); |
59 }, DONT_ENUM); | 66 var index = TO_INTEGER(pos); |
| 67 if (index >= subject.length || index < 0) return ""; |
| 68 return %CharFromCode(%StringCharCodeAt(subject, index)); |
| 69 } |
| 70 |
60 | 71 |
61 // ECMA-262 section 15.5.4.5 | 72 // ECMA-262 section 15.5.4.5 |
62 %AddProperty($String.prototype, "charCodeAt", function charCodeAt(pos) { | 73 function StringCharCodeAt(pos) { |
63 var fast_answer = %_FastCharCodeAt(this, pos); | 74 var fast_answer = %_FastCharCodeAt(this, pos); |
64 if (%_IsSmi(fast_answer)) { | 75 if (%_IsSmi(fast_answer)) { |
65 return fast_answer; | 76 return fast_answer; |
66 } | 77 } |
67 var subject = ToString(this); | 78 var subject = ToString(this); |
68 var index = TO_INTEGER(pos); | 79 var index = TO_INTEGER(pos); |
69 return %StringCharCodeAt(subject, index); | 80 return %StringCharCodeAt(subject, index); |
70 }, DONT_ENUM); | 81 } |
71 | 82 |
72 | 83 |
73 // ECMA-262, section 15.5.4.6 | 84 // ECMA-262, section 15.5.4.6 |
74 %AddProperty($String.prototype, "concat", function concat() { | 85 function StringConcat() { |
75 var len = %_ArgumentsLength(); | 86 var len = %_ArgumentsLength(); |
76 var parts = new $Array(len + 1); | 87 var parts = new $Array(len + 1); |
77 parts[0] = ToString(this); | 88 parts[0] = ToString(this); |
78 for (var i = 0; i < len; i++) | 89 for (var i = 0; i < len; i++) |
79 parts[i + 1] = ToString(%_Arguments(i)); | 90 parts[i + 1] = ToString(%_Arguments(i)); |
80 return parts.join(''); | 91 return parts.join(''); |
81 }, DONT_ENUM); | 92 } |
82 | 93 |
83 // Match ES3 and Safari | 94 // Match ES3 and Safari |
84 %FunctionSetLength($String.prototype.concat, 1); | 95 %FunctionSetLength(StringConcat, 1); |
| 96 |
| 97 |
| 98 // ECMA-262 section 15.5.4.7 |
| 99 function StringIndexOf(searchString /* position */) { // length == 1 |
| 100 var subject_str = ToString(this); |
| 101 var pattern_str = ToString(searchString); |
| 102 var subject_str_len = subject_str.length; |
| 103 var pattern_str_len = pattern_str.length; |
| 104 var index = 0; |
| 105 if (%_ArgumentsLength() > 1) { |
| 106 var arg1 = %_Arguments(1); // position |
| 107 index = TO_INTEGER(arg1); |
| 108 } |
| 109 if (index < 0) index = 0; |
| 110 if (index > subject_str_len) index = subject_str_len; |
| 111 if (pattern_str_len + index > subject_str_len) return -1; |
| 112 return %StringIndexOf(subject_str, pattern_str, index); |
| 113 } |
| 114 |
| 115 |
| 116 // ECMA-262 section 15.5.4.8 |
| 117 function StringLastIndexOf(searchString /* position */) { // length == 1 |
| 118 var sub = ToString(this); |
| 119 var pat = ToString(searchString); |
| 120 var index = (%_ArgumentsLength() > 1) |
| 121 ? ToNumber(%_Arguments(1) /* position */) |
| 122 : $NaN; |
| 123 var firstIndex; |
| 124 if ($isNaN(index)) { |
| 125 firstIndex = sub.length - pat.length; |
| 126 } else { |
| 127 firstIndex = TO_INTEGER(index); |
| 128 if (firstIndex + pat.length > sub.length) { |
| 129 firstIndex = sub.length - pat.length; |
| 130 } |
| 131 } |
| 132 return %StringLastIndexOf(sub, pat, firstIndex); |
| 133 } |
| 134 |
| 135 |
| 136 // ECMA-262 section 15.5.4.9 |
| 137 // |
| 138 // This function is implementation specific. For now, we do not |
| 139 // do anything locale specific. |
| 140 function StringLocaleCompare(other) { |
| 141 if (%_ArgumentsLength() === 0) return 0; |
| 142 |
| 143 var this_str = ToString(this); |
| 144 var other_str = ToString(other); |
| 145 return %StringLocaleCompare(this_str, other_str); |
| 146 } |
| 147 |
| 148 |
| 149 // ECMA-262 section 15.5.4.10 |
| 150 function StringMatch(regexp) { |
| 151 if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp); |
| 152 var subject = ToString(this); |
| 153 |
| 154 if (!regexp.global) return regexp.exec(subject); |
| 155 var matches = DoRegExpExecGlobal(regexp, subject); |
| 156 |
| 157 // If the regexp did not match, return null. |
| 158 if (matches.length == 0) return null; |
| 159 |
| 160 // Build the result array. |
| 161 var result = new $Array(match_string); |
| 162 for (var i = 0; i < matches.length; ++i) { |
| 163 var match = matches[i]; |
| 164 var match_string = subject.slice(match[0], match[1]); |
| 165 result[i] = match_string; |
| 166 } |
| 167 |
| 168 return result; |
| 169 } |
85 | 170 |
86 | 171 |
87 // SubString is an internal function that returns the sub string of 'string'. | 172 // SubString is an internal function that returns the sub string of 'string'. |
88 // If resulting string is of length 1, we use the one character cache | 173 // If resulting string is of length 1, we use the one character cache |
89 // otherwise we call the runtime system. | 174 // otherwise we call the runtime system. |
90 function SubString(string, start, end) { | 175 function SubString(string, start, end) { |
91 // Use the one character string cache. | 176 // Use the one character string cache. |
92 if (start + 1 == end) return %CharFromCode(%StringCharCodeAt(string, start)); | 177 if (start + 1 == end) return %CharFromCode(%StringCharCodeAt(string, start)); |
93 return %StringSlice(string, start, end); | 178 return %StringSlice(string, start, end); |
94 } | 179 } |
95 | 180 |
96 | 181 |
97 // ECMA-262, section 15.5.4.11 | 182 // ECMA-262, section 15.5.4.11 |
98 %AddProperty($String.prototype, "replace", function replace(search, replace) { | 183 function StringReplace(search, replace) { |
99 var subject = ToString(this); | 184 var subject = ToString(this); |
100 | 185 |
101 // Delegate to one of the regular expression variants if necessary. | 186 // Delegate to one of the regular expression variants if necessary. |
102 if (IS_REGEXP(search)) { | 187 if (IS_REGEXP(search)) { |
103 if (IS_FUNCTION(replace)) { | 188 if (IS_FUNCTION(replace)) { |
104 return StringReplaceRegExpWithFunction(subject, search, replace); | 189 return StringReplaceRegExpWithFunction(subject, search, replace); |
105 } else { | 190 } else { |
106 return StringReplaceRegExp(subject, search, replace); | 191 return StringReplaceRegExp(subject, search, replace); |
107 } | 192 } |
108 } | 193 } |
(...skipping 12 matching lines...) Expand all Loading... |
121 if (IS_FUNCTION(replace)) { | 206 if (IS_FUNCTION(replace)) { |
122 builder.add(replace.call(null, search, start, subject)); | 207 builder.add(replace.call(null, search, start, subject)); |
123 } else { | 208 } else { |
124 ExpandReplacement(ToString(replace), subject, [ start, end ], builder); | 209 ExpandReplacement(ToString(replace), subject, [ start, end ], builder); |
125 } | 210 } |
126 | 211 |
127 // suffix | 212 // suffix |
128 builder.add(SubString(subject, end, subject.length)); | 213 builder.add(SubString(subject, end, subject.length)); |
129 | 214 |
130 return builder.generate(); | 215 return builder.generate(); |
131 }, DONT_ENUM); | 216 } |
132 | 217 |
133 | 218 |
134 // Helper function for regular expressions in String.prototype.replace. | 219 // Helper function for regular expressions in String.prototype.replace. |
135 function StringReplaceRegExp(subject, regexp, replace) { | 220 function StringReplaceRegExp(subject, regexp, replace) { |
136 // Compute an array of matches; each match is really a list of | 221 // Compute an array of matches; each match is really a list of |
137 // captures - pairs of (start, end) indexes into the subject string. | 222 // captures - pairs of (start, end) indexes into the subject string. |
138 var matches; | 223 var matches; |
139 if (regexp.global) { | 224 if (regexp.global) { |
140 matches = DoRegExpExecGlobal(regexp, subject); | 225 matches = DoRegExpExecGlobal(regexp, subject); |
141 if (matches.length == 0) return subject; | 226 if (matches.length == 0) return subject; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 var parameters = $Array(m + 2); | 410 var parameters = $Array(m + 2); |
326 for (var j = 0; j < m; j++) { | 411 for (var j = 0; j < m; j++) { |
327 parameters[j] = CaptureString(subject, captures, j); | 412 parameters[j] = CaptureString(subject, captures, j); |
328 } | 413 } |
329 parameters[j] = index; | 414 parameters[j] = index; |
330 parameters[j + 1] = subject; | 415 parameters[j + 1] = subject; |
331 return ToString(replace.apply(null, parameters)); | 416 return ToString(replace.apply(null, parameters)); |
332 } | 417 } |
333 | 418 |
334 | 419 |
335 // ECMA-262 section 15.5.4.7 | |
336 %AddProperty($String.prototype, "indexOf", function indexOf(searchString /* posi
tion */) { // length == 1 | |
337 var subject_str = ToString(this); | |
338 var pattern_str = ToString(searchString); | |
339 var subject_str_len = subject_str.length; | |
340 var pattern_str_len = pattern_str.length; | |
341 var index = 0; | |
342 if (%_ArgumentsLength() > 1) { | |
343 var arg1 = %_Arguments(1); // position | |
344 index = TO_INTEGER(arg1); | |
345 } | |
346 if (index < 0) index = 0; | |
347 if (index > subject_str_len) index = subject_str_len; | |
348 if (pattern_str_len + index > subject_str_len) return -1; | |
349 return %StringIndexOf(subject_str, pattern_str, index); | |
350 }, DONT_ENUM); | |
351 | |
352 | |
353 // ECMA-262 section 15.5.4.8 | |
354 %AddProperty($String.prototype, "lastIndexOf", function lastIndexOf(searchString
/* position */) { // length == 1 | |
355 var sub = ToString(this); | |
356 var pat = ToString(searchString); | |
357 var index = (%_ArgumentsLength() > 1) | |
358 ? ToNumber(%_Arguments(1) /* position */) | |
359 : $NaN; | |
360 var firstIndex; | |
361 if ($isNaN(index)) { | |
362 firstIndex = sub.length - pat.length; | |
363 } else { | |
364 firstIndex = TO_INTEGER(index); | |
365 if (firstIndex + pat.length > sub.length) { | |
366 firstIndex = sub.length - pat.length; | |
367 } | |
368 } | |
369 return %StringLastIndexOf(sub, pat, firstIndex); | |
370 }, DONT_ENUM); | |
371 | |
372 | |
373 // ECMA-262 section 15.5.4.9 | |
374 // | |
375 // This function is implementation specific. For now, we do not | |
376 // do anything locale specific. | |
377 %AddProperty($String.prototype, "localeCompare", function localeCompare(other) { | |
378 if (%_ArgumentsLength() === 0) return 0; | |
379 | |
380 var this_str = ToString(this); | |
381 var other_str = ToString(other); | |
382 return %StringLocaleCompare(this_str, other_str); | |
383 }, DONT_ENUM); | |
384 | |
385 | |
386 // ECMA-262 section 15.5.4.10 | |
387 %AddProperty($String.prototype, "match", function match(regexp) { | |
388 if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp); | |
389 var subject = ToString(this); | |
390 | |
391 if (!regexp.global) return regexp.exec(subject); | |
392 var matches = DoRegExpExecGlobal(regexp, subject); | |
393 | |
394 // If the regexp did not match, return null. | |
395 if (matches.length == 0) return null; | |
396 | |
397 // Build the result array. | |
398 var result = new $Array(match_string); | |
399 for (var i = 0; i < matches.length; ++i) { | |
400 var match = matches[i]; | |
401 var match_string = subject.slice(match[0], match[1]); | |
402 result[i] = match_string; | |
403 } | |
404 | |
405 return result; | |
406 }, DONT_ENUM); | |
407 | |
408 | |
409 // ECMA-262 section 15.5.4.12 | 420 // ECMA-262 section 15.5.4.12 |
410 %AddProperty($String.prototype, "search", function search(re) { | 421 function StringSearch(re) { |
411 var regexp = new ORIGINAL_REGEXP(re); | 422 var regexp = new ORIGINAL_REGEXP(re); |
412 var s = ToString(this); | 423 var s = ToString(this); |
413 var last_idx = regexp.lastIndex; // keep old lastIndex | 424 var last_idx = regexp.lastIndex; // keep old lastIndex |
414 regexp.lastIndex = 0; // ignore re.global property | 425 regexp.lastIndex = 0; // ignore re.global property |
415 var result = regexp.exec(s); | 426 var result = regexp.exec(s); |
416 regexp.lastIndex = last_idx; // restore lastIndex | 427 regexp.lastIndex = last_idx; // restore lastIndex |
417 if (result == null) | 428 if (result == null) |
418 return -1; | 429 return -1; |
419 else | 430 else |
420 return result.index; | 431 return result.index; |
421 }, DONT_ENUM); | 432 } |
422 | 433 |
423 | 434 |
424 // ECMA-262 section 15.5.4.13 | 435 // ECMA-262 section 15.5.4.13 |
425 %AddProperty($String.prototype, "slice", function slice(start, end) { | 436 function StringSlice(start, end) { |
426 var s = ToString(this); | 437 var s = ToString(this); |
427 var s_len = s.length; | 438 var s_len = s.length; |
428 var start_i = TO_INTEGER(start); | 439 var start_i = TO_INTEGER(start); |
429 var end_i = s_len; | 440 var end_i = s_len; |
430 if (end !== void 0) | 441 if (end !== void 0) |
431 end_i = TO_INTEGER(end); | 442 end_i = TO_INTEGER(end); |
432 | 443 |
433 if (start_i < 0) { | 444 if (start_i < 0) { |
434 start_i += s_len; | 445 start_i += s_len; |
435 if (start_i < 0) | 446 if (start_i < 0) |
(...skipping 10 matching lines...) Expand all Loading... |
446 } else { | 457 } else { |
447 if (end_i > s_len) | 458 if (end_i > s_len) |
448 end_i = s_len; | 459 end_i = s_len; |
449 } | 460 } |
450 | 461 |
451 var num_c = end_i - start_i; | 462 var num_c = end_i - start_i; |
452 if (num_c < 0) | 463 if (num_c < 0) |
453 num_c = 0; | 464 num_c = 0; |
454 | 465 |
455 return SubString(s, start_i, start_i + num_c); | 466 return SubString(s, start_i, start_i + num_c); |
456 }, DONT_ENUM); | 467 } |
457 | 468 |
458 | 469 |
459 // ECMA-262 section 15.5.4.14 | 470 // ECMA-262 section 15.5.4.14 |
460 %AddProperty($String.prototype, "split", function split(separator, limit) { | 471 function StringSplit(separator, limit) { |
461 var subject = ToString(this); | 472 var subject = ToString(this); |
462 var result = []; | 473 var result = []; |
463 var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit); | 474 var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit); |
464 | 475 |
465 if (lim === 0) return result; | 476 if (lim === 0) return result; |
466 | 477 |
467 // ECMA-262 says that if separator is undefined, the result should | 478 // ECMA-262 says that if separator is undefined, the result should |
468 // be an array of size 1 containing the entire string. SpiderMonkey | 479 // be an array of size 1 containing the entire string. SpiderMonkey |
469 // and KJS have this behaviour only when no separator is given. If | 480 // and KJS have this behaviour only when no separator is given. If |
470 // undefined is explicitly given, they convert it to a string and | 481 // undefined is explicitly given, they convert it to a string and |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 result[result.length] = match[1]; | 522 result[result.length] = match[1]; |
512 if (result.length === lim) return result; | 523 if (result.length === lim) return result; |
513 | 524 |
514 for (var i = 2; i < match.length; i++) { | 525 for (var i = 2; i < match.length; i++) { |
515 result[result.length] = match[i]; | 526 result[result.length] = match[i]; |
516 if (result.length === lim) return result; | 527 if (result.length === lim) return result; |
517 } | 528 } |
518 | 529 |
519 startIndex = currentIndex = endIndex; | 530 startIndex = currentIndex = endIndex; |
520 } | 531 } |
521 }, DONT_ENUM); | 532 } |
522 | 533 |
523 | 534 |
524 // ECMA-262 section 15.5.4.14 | 535 // ECMA-262 section 15.5.4.14 |
525 // Helper function used by split. | 536 // Helper function used by split. |
526 function splitMatch(separator, subject, current_index, start_index) { | 537 function splitMatch(separator, subject, current_index, start_index) { |
527 if (IS_REGEXP(separator)) { | 538 if (IS_REGEXP(separator)) { |
528 var ovector = DoRegExpExec(separator, subject, start_index); | 539 var ovector = DoRegExpExec(separator, subject, start_index); |
529 if (ovector == null) return null; | 540 if (ovector == null) return null; |
530 var nof_results = ovector.length >> 1; | 541 var nof_results = ovector.length >> 1; |
531 var result = new $Array(nof_results + 1); | 542 var result = new $Array(nof_results + 1); |
(...skipping 10 matching lines...) Expand all Loading... |
542 } | 553 } |
543 | 554 |
544 var separatorIndex = subject.indexOf(separator, start_index); | 555 var separatorIndex = subject.indexOf(separator, start_index); |
545 if (separatorIndex === -1) return null; | 556 if (separatorIndex === -1) return null; |
546 | 557 |
547 return [ separatorIndex + separator.length, subject.slice(current_index, separ
atorIndex) ]; | 558 return [ separatorIndex + separator.length, subject.slice(current_index, separ
atorIndex) ]; |
548 }; | 559 }; |
549 | 560 |
550 | 561 |
551 // ECMA-262 section 15.5.4.15 | 562 // ECMA-262 section 15.5.4.15 |
552 %AddProperty($String.prototype, "substring", function substring(start, end) { | 563 function StringSubstring(start, end) { |
553 var s = ToString(this); | 564 var s = ToString(this); |
554 var s_len = s.length; | 565 var s_len = s.length; |
555 var start_i = TO_INTEGER(start); | 566 var start_i = TO_INTEGER(start); |
556 var end_i = s_len; | 567 var end_i = s_len; |
557 if (!IS_UNDEFINED(end)) | 568 if (!IS_UNDEFINED(end)) |
558 end_i = TO_INTEGER(end); | 569 end_i = TO_INTEGER(end); |
559 | 570 |
560 if (start_i < 0) start_i = 0; | 571 if (start_i < 0) start_i = 0; |
561 if (start_i > s_len) start_i = s_len; | 572 if (start_i > s_len) start_i = s_len; |
562 if (end_i < 0) end_i = 0; | 573 if (end_i < 0) end_i = 0; |
563 if (end_i > s_len) end_i = s_len; | 574 if (end_i > s_len) end_i = s_len; |
564 | 575 |
565 if (start_i > end_i) { | 576 if (start_i > end_i) { |
566 var tmp = end_i; | 577 var tmp = end_i; |
567 end_i = start_i; | 578 end_i = start_i; |
568 start_i = tmp; | 579 start_i = tmp; |
569 } | 580 } |
570 | 581 |
571 return SubString(s, start_i, end_i); | 582 return SubString(s, start_i, end_i); |
572 }, DONT_ENUM); | 583 } |
573 | 584 |
574 | 585 |
575 // This is not a part of ECMA-262. | 586 // This is not a part of ECMA-262. |
576 %AddProperty($String.prototype, "substr", function substr(start, n) { | 587 function StringSubstr(start, n) { |
577 var s = ToString(this); | 588 var s = ToString(this); |
578 var len; | 589 var len; |
579 | 590 |
580 // Correct n: If not given, set to string length; if explicitly | 591 // Correct n: If not given, set to string length; if explicitly |
581 // set to undefined, zero, or negative, returns empty string. | 592 // set to undefined, zero, or negative, returns empty string. |
582 if (n === void 0) { | 593 if (n === void 0) { |
583 len = s.length; | 594 len = s.length; |
584 } else { | 595 } else { |
585 len = TO_INTEGER(n); | 596 len = TO_INTEGER(n); |
586 if (len <= 0) return ''; | 597 if (len <= 0) return ''; |
(...skipping 13 matching lines...) Expand all Loading... |
600 if (start < 0) { | 611 if (start < 0) { |
601 start += s.length; | 612 start += s.length; |
602 if (start < 0) start = 0; | 613 if (start < 0) start = 0; |
603 } | 614 } |
604 } | 615 } |
605 | 616 |
606 var end = start + len; | 617 var end = start + len; |
607 if (end > s.length) end = s.length; | 618 if (end > s.length) end = s.length; |
608 | 619 |
609 return SubString(s, start, end); | 620 return SubString(s, start, end); |
610 }, DONT_ENUM); | 621 } |
611 | 622 |
612 | 623 |
613 // ECMA-262, 15.5.4.16 | 624 // ECMA-262, 15.5.4.16 |
614 %AddProperty($String.prototype, "toLowerCase", function toLowerCase() { | 625 function StringToLowerCase() { |
615 return %StringToLowerCase(ToString(this)); | 626 return %StringToLowerCase(ToString(this)); |
616 }, DONT_ENUM); | 627 } |
617 | 628 |
618 | 629 |
619 // ECMA-262, 15.5.4.17 | 630 // ECMA-262, 15.5.4.17 |
620 %AddProperty($String.prototype, "toLocaleLowerCase", function toLocaleLowerCase(
) { | 631 function StringToLocaleLowerCase() { |
621 return %StringToLowerCase(ToString(this)); | 632 return %StringToLowerCase(ToString(this)); |
622 }, DONT_ENUM); | 633 } |
623 | 634 |
624 | 635 |
625 // ECMA-262, 15.5.4.18 | 636 // ECMA-262, 15.5.4.18 |
626 %AddProperty($String.prototype, "toUpperCase", function toUpperCase() { | 637 function StringToUpperCase() { |
627 return %StringToUpperCase(ToString(this)); | 638 return %StringToUpperCase(ToString(this)); |
628 }, DONT_ENUM); | 639 } |
629 | 640 |
630 | 641 |
631 // ECMA-262, 15.5.4.19 | 642 // ECMA-262, 15.5.4.19 |
632 %AddProperty($String.prototype, "toLocaleUpperCase", function toLocaleUpperCase(
) { | 643 function StringToLocaleUpperCase() { |
633 return %StringToUpperCase(ToString(this)); | 644 return %StringToUpperCase(ToString(this)); |
634 }, DONT_ENUM); | 645 } |
635 | 646 |
636 | 647 |
637 // ECMA-262, section 15.5.3.2 | 648 // ECMA-262, section 15.5.3.2 |
638 %AddProperty($String, "fromCharCode", function fromCharCode(code) { | 649 function StringFromCharCode(code) { |
639 var n = %_ArgumentsLength(); | 650 var n = %_ArgumentsLength(); |
640 if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff) | 651 if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff) |
641 | 652 |
642 // NOTE: This is not super-efficient, but it is necessary because we | 653 // NOTE: This is not super-efficient, but it is necessary because we |
643 // want to avoid converting to numbers from within the virtual | 654 // want to avoid converting to numbers from within the virtual |
644 // machine. Maybe we can find another way of doing this? | 655 // machine. Maybe we can find another way of doing this? |
645 var codes = new $Array(n); | 656 var codes = new $Array(n); |
646 for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i)); | 657 for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i)); |
647 return %StringFromCharCodeArray(codes); | 658 return %StringFromCharCodeArray(codes); |
648 }, DONT_ENUM); | 659 } |
649 | |
650 | |
651 // ECMA-262, section 15.5.4.4 | |
652 function charAt(pos) { | |
653 var subject = ToString(this); | |
654 var index = TO_INTEGER(pos); | |
655 if (index >= subject.length || index < 0) return ""; | |
656 return %CharFromCode(%StringCharCodeAt(subject, index)); | |
657 }; | |
658 | |
659 %AddProperty($String.prototype, "charAt", charAt, DONT_ENUM); | |
660 | 660 |
661 | 661 |
662 // Helper function for very basic XSS protection. | 662 // Helper function for very basic XSS protection. |
663 function HtmlEscape(str) { | 663 function HtmlEscape(str) { |
664 return ToString(str).replace(/</g, "<") | 664 return ToString(str).replace(/</g, "<") |
665 .replace(/>/g, ">") | 665 .replace(/>/g, ">") |
666 .replace(/"/g, """) | 666 .replace(/"/g, """) |
667 .replace(/'/g, "'"); | 667 .replace(/'/g, "'"); |
668 }; | 668 }; |
669 | 669 |
670 | 670 |
671 // Compatibility support for KJS. | 671 // Compatibility support for KJS. |
672 // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js. | 672 // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js. |
673 %AddProperty($String.prototype, "link", function link(s) { | 673 function StringLink(s) { |
674 return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>"; | 674 return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>"; |
675 }, DONT_ENUM); | 675 } |
676 | 676 |
677 | 677 |
678 %AddProperty($String.prototype, "anchor", function anchor(name) { | 678 function StringAnchor(name) { |
679 return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>"; | 679 return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>"; |
680 }, DONT_ENUM); | 680 } |
681 | 681 |
682 | 682 |
683 %AddProperty($String.prototype, "fontcolor", function fontcolor(color) { | 683 function StringFontcolor(color) { |
684 return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>"; | 684 return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>"; |
685 }, DONT_ENUM); | 685 } |
686 | 686 |
687 | 687 |
688 %AddProperty($String.prototype, "fontsize", function fontsize(size) { | 688 function StringFontsize(size) { |
689 return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>"; | 689 return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>"; |
690 }, DONT_ENUM); | 690 } |
691 | 691 |
692 | 692 |
693 %AddProperty($String.prototype, "big", function big() { | 693 function StringBig() { |
694 return "<big>" + this + "</big>"; | 694 return "<big>" + this + "</big>"; |
695 }, DONT_ENUM); | 695 } |
696 | 696 |
697 | 697 |
698 %AddProperty($String.prototype, "blink", function blink() { | 698 function StringBlink() { |
699 return "<blink>" + this + "</blink>"; | 699 return "<blink>" + this + "</blink>"; |
700 }, DONT_ENUM); | 700 } |
701 | 701 |
702 | 702 |
703 %AddProperty($String.prototype, "bold", function bold() { | 703 function StringBold() { |
704 return "<b>" + this + "</b>"; | 704 return "<b>" + this + "</b>"; |
705 }, DONT_ENUM); | 705 } |
706 | 706 |
707 | 707 |
708 %AddProperty($String.prototype, "fixed", function fixed() { | 708 function StringFixed() { |
709 return "<tt>" + this + "</tt>"; | 709 return "<tt>" + this + "</tt>"; |
710 }, DONT_ENUM); | 710 } |
711 | 711 |
712 | 712 |
713 %AddProperty($String.prototype, "italics", function italics() { | 713 function StringItalics() { |
714 return "<i>" + this + "</i>"; | 714 return "<i>" + this + "</i>"; |
715 }, DONT_ENUM); | 715 } |
716 | 716 |
717 | 717 |
718 %AddProperty($String.prototype, "small", function small() { | 718 function StringSmall() { |
719 return "<small>" + this + "</small>"; | 719 return "<small>" + this + "</small>"; |
720 }, DONT_ENUM); | 720 } |
721 | 721 |
722 | 722 |
723 %AddProperty($String.prototype, "strike", function strike() { | 723 function StringStrike() { |
724 return "<strike>" + this + "</strike>"; | 724 return "<strike>" + this + "</strike>"; |
725 }, DONT_ENUM); | 725 } |
726 | 726 |
727 | 727 |
728 %AddProperty($String.prototype, "sub", function sub() { | 728 function StringSub() { |
729 return "<sub>" + this + "</sub>"; | 729 return "<sub>" + this + "</sub>"; |
730 }, DONT_ENUM); | 730 } |
731 | 731 |
732 | 732 |
733 %AddProperty($String.prototype, "sup", function sup() { | 733 function StringSup() { |
734 return "<sup>" + this + "</sup>"; | 734 return "<sup>" + this + "</sup>"; |
735 }, DONT_ENUM); | 735 } |
736 | 736 |
737 | 737 |
738 // StringBuilder support. | 738 // StringBuilder support. |
739 | 739 |
740 function StringBuilder() { | 740 function StringBuilder() { |
741 this.elements = new $Array(); | 741 this.elements = new $Array(); |
742 } | 742 } |
743 | 743 |
744 | 744 |
745 function ReplaceResultBuilder(str) { | 745 function ReplaceResultBuilder(str) { |
(...skipping 25 matching lines...) Expand all Loading... |
771 | 771 |
772 | 772 |
773 StringBuilder.prototype.generate = function() { | 773 StringBuilder.prototype.generate = function() { |
774 return %StringBuilderConcat(this.elements, ""); | 774 return %StringBuilderConcat(this.elements, ""); |
775 } | 775 } |
776 | 776 |
777 | 777 |
778 ReplaceResultBuilder.prototype.generate = function() { | 778 ReplaceResultBuilder.prototype.generate = function() { |
779 return %StringBuilderConcat(this.elements, this.special_string); | 779 return %StringBuilderConcat(this.elements, this.special_string); |
780 } | 780 } |
| 781 |
| 782 |
| 783 // ------------------------------------------------------------------- |
| 784 |
| 785 function SetupString() { |
| 786 // Setup the constructor property on the String prototype object. |
| 787 %AddProperty($String.prototype, "constructor", $String, DONT_ENUM); |
| 788 |
| 789 |
| 790 // Setup the non-enumerable functions on the String object. |
| 791 InstallFunctions($String, DONT_ENUM, $Array( |
| 792 "fromCharCode", StringFromCharCode |
| 793 )); |
| 794 |
| 795 |
| 796 // Setup the non-enumerable functions on the String prototype object. |
| 797 InstallFunctions($String.prototype, DONT_ENUM, $Array( |
| 798 "valueOf", StringValueOf, |
| 799 "toString", StringToString, |
| 800 "charAt", StringCharAt, |
| 801 "charCodeAt", StringCharCodeAt, |
| 802 "concat", StringConcat, |
| 803 "indexOf", StringIndexOf, |
| 804 "lastIndexOf", StringLastIndexOf, |
| 805 "localeCompare", StringLocaleCompare, |
| 806 "match", StringMatch, |
| 807 "replace", StringReplace, |
| 808 "search", StringSearch, |
| 809 "slice", StringSlice, |
| 810 "split", StringSplit, |
| 811 "substring", StringSubstring, |
| 812 "substr", StringSubstr, |
| 813 "toLowerCase", StringToLowerCase, |
| 814 "toLocaleLowerCase", StringToLocaleLowerCase, |
| 815 "toUpperCase", StringToUpperCase, |
| 816 "toLocaleUpperCase", StringToLocaleUpperCase, |
| 817 "link", StringLink, |
| 818 "anchor", StringAnchor, |
| 819 "fontcolor", StringFontcolor, |
| 820 "fontsize", StringFontsize, |
| 821 "big", StringBig, |
| 822 "blink", StringBlink, |
| 823 "bold", StringBold, |
| 824 "fixed", StringFixed, |
| 825 "italics", StringItalics, |
| 826 "small", StringSmall, |
| 827 "strike", StringStrike, |
| 828 "sub", StringSub, |
| 829 "sup", StringSup |
| 830 )); |
| 831 } |
| 832 |
| 833 |
| 834 SetupString(); |
OLD | NEW |