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 28 matching lines...) Expand all Loading... |
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 %AddProperty($String.prototype, "constructor", $String, DONT_ENUM); |
48 | 48 |
49 %AddProperty($String.prototype, "valueOf", function() { | 49 %AddProperty($String.prototype, "valueOf", function valueOf() { |
50 if (!IS_STRING(this) && %ClassOf(this) !== 'String') | 50 if (!IS_STRING(this) && %ClassOf(this) !== 'String') |
51 throw new $TypeError('String.prototype.valueOf is not generic'); | 51 throw new $TypeError('String.prototype.valueOf is not generic'); |
52 return %_ValueOf(this); | 52 return %_ValueOf(this); |
53 }, DONT_ENUM); | 53 }, DONT_ENUM); |
54 | 54 |
55 | 55 %AddProperty($String.prototype, "toString", function toString() { |
56 %AddProperty($String.prototype, "toString", $String.prototype.valueOf, DONT_ENUM
); | 56 if (!IS_STRING(this) && %ClassOf(this) !== 'String') |
| 57 throw new $TypeError('String.prototype.toString is not generic'); |
| 58 return %_ValueOf(this); |
| 59 }, DONT_ENUM); |
57 | 60 |
58 // ECMA-262 section 15.5.4.5 | 61 // ECMA-262 section 15.5.4.5 |
59 %AddProperty($String.prototype, "charCodeAt", function(pos) { | 62 %AddProperty($String.prototype, "charCodeAt", function charCodeAt(pos) { |
60 var fast_answer = %_FastCharCodeAt(this, pos); | 63 var fast_answer = %_FastCharCodeAt(this, pos); |
61 if (%_IsSmi(fast_answer)) { | 64 if (%_IsSmi(fast_answer)) { |
62 return fast_answer; | 65 return fast_answer; |
63 } | 66 } |
64 var subject = ToString(this); | 67 var subject = ToString(this); |
65 var index = TO_INTEGER(pos); | 68 var index = TO_INTEGER(pos); |
66 return %StringCharCodeAt(subject, index); | 69 return %StringCharCodeAt(subject, index); |
67 }, DONT_ENUM); | 70 }, DONT_ENUM); |
68 | 71 |
69 | 72 |
70 // ECMA-262, section 15.5.4.6 | 73 // ECMA-262, section 15.5.4.6 |
71 %AddProperty($String.prototype, "concat", function() { | 74 %AddProperty($String.prototype, "concat", function concat() { |
72 var len = %_ArgumentsLength(); | 75 var len = %_ArgumentsLength(); |
73 var parts = new $Array(len + 1); | 76 var parts = new $Array(len + 1); |
74 parts[0] = ToString(this); | 77 parts[0] = ToString(this); |
75 for (var i = 0; i < len; i++) | 78 for (var i = 0; i < len; i++) |
76 parts[i + 1] = ToString(%_Arguments(i)); | 79 parts[i + 1] = ToString(%_Arguments(i)); |
77 return parts.join(''); | 80 return parts.join(''); |
78 }, DONT_ENUM); | 81 }, DONT_ENUM); |
79 | 82 |
80 // Match ES3 and Safari | 83 // Match ES3 and Safari |
81 %FunctionSetLength($String.prototype.concat, 1); | 84 %FunctionSetLength($String.prototype.concat, 1); |
82 | 85 |
83 | 86 |
84 // SubString is an internal function that returns the sub string of 'string'. | 87 // SubString is an internal function that returns the sub string of 'string'. |
85 // If resulting string is of length 1, we use the one character cache | 88 // If resulting string is of length 1, we use the one character cache |
86 // otherwise we call the runtime system. | 89 // otherwise we call the runtime system. |
87 function SubString(string, start, end) { | 90 function SubString(string, start, end) { |
88 // Use the one character string cache. | 91 // Use the one character string cache. |
89 if (start + 1 == end) return %CharFromCode(%StringCharCodeAt(string, start)); | 92 if (start + 1 == end) return %CharFromCode(%StringCharCodeAt(string, start)); |
90 return %StringSlice(string, start, end); | 93 return %StringSlice(string, start, end); |
91 } | 94 } |
92 | 95 |
93 | 96 |
94 // ECMA-262, section 15.5.4.11 | 97 // ECMA-262, section 15.5.4.11 |
95 %AddProperty($String.prototype, "replace", function (search, replace) { | 98 %AddProperty($String.prototype, "replace", function replace(search, replace) { |
96 var subject = ToString(this); | 99 var subject = ToString(this); |
97 | 100 |
98 // Delegate to one of the regular expression variants if necessary. | 101 // Delegate to one of the regular expression variants if necessary. |
99 if (IS_REGEXP(search)) { | 102 if (IS_REGEXP(search)) { |
100 if (IS_FUNCTION(replace)) { | 103 if (IS_FUNCTION(replace)) { |
101 return StringReplaceRegExpWithFunction(subject, search, replace); | 104 return StringReplaceRegExpWithFunction(subject, search, replace); |
102 } else { | 105 } else { |
103 return StringReplaceRegExp(subject, search, replace); | 106 return StringReplaceRegExp(subject, search, replace); |
104 } | 107 } |
105 } | 108 } |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 for (var j = 0; j < m; j++) { | 326 for (var j = 0; j < m; j++) { |
324 parameters[j] = CaptureString(subject, captures, j); | 327 parameters[j] = CaptureString(subject, captures, j); |
325 } | 328 } |
326 parameters[j] = index; | 329 parameters[j] = index; |
327 parameters[j + 1] = subject; | 330 parameters[j + 1] = subject; |
328 return ToString(replace.apply(null, parameters)); | 331 return ToString(replace.apply(null, parameters)); |
329 } | 332 } |
330 | 333 |
331 | 334 |
332 // ECMA-262 section 15.5.4.7 | 335 // ECMA-262 section 15.5.4.7 |
333 %AddProperty($String.prototype, "indexOf", function(searchString /* position */)
{ // length == 1 | 336 %AddProperty($String.prototype, "indexOf", function indexOf(searchString /* posi
tion */) { // length == 1 |
334 var subject_str = ToString(this); | 337 var subject_str = ToString(this); |
335 var pattern_str = ToString(searchString); | 338 var pattern_str = ToString(searchString); |
336 var subject_str_len = subject_str.length; | 339 var subject_str_len = subject_str.length; |
337 var pattern_str_len = pattern_str.length; | 340 var pattern_str_len = pattern_str.length; |
338 var index = 0; | 341 var index = 0; |
339 if (%_ArgumentsLength() > 1) { | 342 if (%_ArgumentsLength() > 1) { |
340 var arg1 = %_Arguments(1); // position | 343 var arg1 = %_Arguments(1); // position |
341 index = TO_INTEGER(arg1); | 344 index = TO_INTEGER(arg1); |
342 } | 345 } |
343 if (index < 0) index = 0; | 346 if (index < 0) index = 0; |
344 if (index > subject_str_len) index = subject_str_len; | 347 if (index > subject_str_len) index = subject_str_len; |
345 if (pattern_str_len + index > subject_str_len) return -1; | 348 if (pattern_str_len + index > subject_str_len) return -1; |
346 return %StringIndexOf(subject_str, pattern_str, index); | 349 return %StringIndexOf(subject_str, pattern_str, index); |
347 }, DONT_ENUM); | 350 }, DONT_ENUM); |
348 | 351 |
349 | 352 |
350 // ECMA-262 section 15.5.4.8 | 353 // ECMA-262 section 15.5.4.8 |
351 %AddProperty($String.prototype, "lastIndexOf", function(searchString /* position
*/) { // length == 1 | 354 %AddProperty($String.prototype, "lastIndexOf", function lastIndexOf(searchString
/* position */) { // length == 1 |
352 var sub = ToString(this); | 355 var sub = ToString(this); |
353 var pat = ToString(searchString); | 356 var pat = ToString(searchString); |
354 var index = (%_ArgumentsLength() > 1) | 357 var index = (%_ArgumentsLength() > 1) |
355 ? ToNumber(%_Arguments(1) /* position */) | 358 ? ToNumber(%_Arguments(1) /* position */) |
356 : $NaN; | 359 : $NaN; |
357 var firstIndex; | 360 var firstIndex; |
358 if ($isNaN(index)) { | 361 if ($isNaN(index)) { |
359 firstIndex = sub.length - pat.length; | 362 firstIndex = sub.length - pat.length; |
360 } else { | 363 } else { |
361 firstIndex = TO_INTEGER(index); | 364 firstIndex = TO_INTEGER(index); |
362 if (firstIndex + pat.length > sub.length) { | 365 if (firstIndex + pat.length > sub.length) { |
363 firstIndex = sub.length - pat.length; | 366 firstIndex = sub.length - pat.length; |
364 } | 367 } |
365 } | 368 } |
366 return %StringLastIndexOf(sub, pat, firstIndex); | 369 return %StringLastIndexOf(sub, pat, firstIndex); |
367 }, DONT_ENUM); | 370 }, DONT_ENUM); |
368 | 371 |
369 | 372 |
370 // ECMA-262 section 15.5.4.9 | 373 // ECMA-262 section 15.5.4.9 |
371 // | 374 // |
372 // This function is implementation specific. For now, we do not | 375 // This function is implementation specific. For now, we do not |
373 // do anything locale specific. | 376 // do anything locale specific. |
374 %AddProperty($String.prototype, "localeCompare", function(other) { | 377 %AddProperty($String.prototype, "localeCompare", function localeCompare(other) { |
375 if (%_ArgumentsLength() === 0) return 0; | 378 if (%_ArgumentsLength() === 0) return 0; |
376 | 379 |
377 var this_str = ToString(this); | 380 var this_str = ToString(this); |
378 var other_str = ToString(other); | 381 var other_str = ToString(other); |
379 return %StringLocaleCompare(this_str, other_str); | 382 return %StringLocaleCompare(this_str, other_str); |
380 }, DONT_ENUM); | 383 }, DONT_ENUM); |
381 | 384 |
382 | 385 |
383 // ECMA-262 section 15.5.4.10 | 386 // ECMA-262 section 15.5.4.10 |
384 %AddProperty($String.prototype, "match", function(regexp) { | 387 %AddProperty($String.prototype, "match", function match(regexp) { |
385 if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp); | 388 if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp); |
386 var subject = ToString(this); | 389 var subject = ToString(this); |
387 | 390 |
388 if (!regexp.global) return regexp.exec(subject); | 391 if (!regexp.global) return regexp.exec(subject); |
389 var matches = DoRegExpExecGlobal(regexp, subject); | 392 var matches = DoRegExpExecGlobal(regexp, subject); |
390 | 393 |
391 // If the regexp did not match, return null. | 394 // If the regexp did not match, return null. |
392 if (matches.length == 0) return null; | 395 if (matches.length == 0) return null; |
393 | 396 |
394 // Build the result array. | 397 // Build the result array. |
395 var result = new $Array(match_string); | 398 var result = new $Array(match_string); |
396 for (var i = 0; i < matches.length; ++i) { | 399 for (var i = 0; i < matches.length; ++i) { |
397 var match = matches[i]; | 400 var match = matches[i]; |
398 var match_string = subject.slice(match[0], match[1]); | 401 var match_string = subject.slice(match[0], match[1]); |
399 result[i] = match_string; | 402 result[i] = match_string; |
400 } | 403 } |
401 | 404 |
402 return result; | 405 return result; |
403 }, DONT_ENUM); | 406 }, DONT_ENUM); |
404 | 407 |
405 | 408 |
406 // ECMA-262 section 15.5.4.12 | 409 // ECMA-262 section 15.5.4.12 |
407 %AddProperty($String.prototype, "search", function(re) { | 410 %AddProperty($String.prototype, "search", function search(re) { |
408 var regexp = new ORIGINAL_REGEXP(re); | 411 var regexp = new ORIGINAL_REGEXP(re); |
409 var s = ToString(this); | 412 var s = ToString(this); |
410 var last_idx = regexp.lastIndex; // keep old lastIndex | 413 var last_idx = regexp.lastIndex; // keep old lastIndex |
411 regexp.lastIndex = 0; // ignore re.global property | 414 regexp.lastIndex = 0; // ignore re.global property |
412 var result = regexp.exec(s); | 415 var result = regexp.exec(s); |
413 regexp.lastIndex = last_idx; // restore lastIndex | 416 regexp.lastIndex = last_idx; // restore lastIndex |
414 if (result == null) | 417 if (result == null) |
415 return -1; | 418 return -1; |
416 else | 419 else |
417 return result.index; | 420 return result.index; |
418 }, DONT_ENUM); | 421 }, DONT_ENUM); |
419 | 422 |
420 | 423 |
421 // ECMA-262 section 15.5.4.13 | 424 // ECMA-262 section 15.5.4.13 |
422 %AddProperty($String.prototype, "slice", function(start, end) { | 425 %AddProperty($String.prototype, "slice", function slice(start, end) { |
423 var s = ToString(this); | 426 var s = ToString(this); |
424 var s_len = s.length; | 427 var s_len = s.length; |
425 var start_i = TO_INTEGER(start); | 428 var start_i = TO_INTEGER(start); |
426 var end_i = s_len; | 429 var end_i = s_len; |
427 if (end !== void 0) | 430 if (end !== void 0) |
428 end_i = TO_INTEGER(end); | 431 end_i = TO_INTEGER(end); |
429 | 432 |
430 if (start_i < 0) { | 433 if (start_i < 0) { |
431 start_i += s_len; | 434 start_i += s_len; |
432 if (start_i < 0) | 435 if (start_i < 0) |
(...skipping 14 matching lines...) Expand all Loading... |
447 | 450 |
448 var num_c = end_i - start_i; | 451 var num_c = end_i - start_i; |
449 if (num_c < 0) | 452 if (num_c < 0) |
450 num_c = 0; | 453 num_c = 0; |
451 | 454 |
452 return SubString(s, start_i, start_i + num_c); | 455 return SubString(s, start_i, start_i + num_c); |
453 }, DONT_ENUM); | 456 }, DONT_ENUM); |
454 | 457 |
455 | 458 |
456 // ECMA-262 section 15.5.4.14 | 459 // ECMA-262 section 15.5.4.14 |
457 %AddProperty($String.prototype, "split", function(separator, limit) { | 460 %AddProperty($String.prototype, "split", function split(separator, limit) { |
458 var subject = ToString(this); | 461 var subject = ToString(this); |
459 var result = []; | 462 var result = []; |
460 var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit); | 463 var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit); |
461 | 464 |
462 if (lim === 0) return result; | 465 if (lim === 0) return result; |
463 | 466 |
464 // ECMA-262 says that if separator is undefined, the result should | 467 // ECMA-262 says that if separator is undefined, the result should |
465 // be an array of size 1 containing the entire string. SpiderMonkey | 468 // be an array of size 1 containing the entire string. SpiderMonkey |
466 // and KJS have this behaviour only when no separator is given. If | 469 // and KJS have this behaviour only when no separator is given. If |
467 // undefined is explicitly given, they convert it to a string and | 470 // undefined is explicitly given, they convert it to a string and |
468 // use that. We do as SpiderMonkey and KJS. | 471 // use that. We do as SpiderMonkey and KJS. |
469 if (%_ArgumentsLength() === 0) { | 472 if (%_ArgumentsLength() === 0) { |
470 result[result.length] = subject; | 473 result[result.length] = subject; |
471 return result; | 474 return result; |
472 } | 475 } |
473 | 476 |
474 var length = subject.length; | 477 var length = subject.length; |
475 var currentIndex = 0; | 478 var currentIndex = 0; |
476 var startIndex = 0; | 479 var startIndex = 0; |
477 | 480 |
478 var sep = IS_REGEXP(separator) ? separator : ToString(separator); | 481 var sep = IS_REGEXP(separator) ? separator : ToString(separator); |
479 | 482 |
480 if (length === 0) { | 483 if (length === 0) { |
481 if (splitMatch(sep, subject, 0, 0) != null) return result; | 484 if (splitMatch(sep, subject, 0, 0) != null) return result; |
482 result[result.length] = subject; | 485 result[result.length] = subject; |
483 return result; | 486 return result; |
484 } | 487 } |
485 | 488 |
486 while (true) { | 489 while (true) { |
487 | 490 |
488 if (startIndex === length) { | 491 if (startIndex === length) { |
489 result[result.length] = subject.slice(currentIndex, length); | 492 result[result.length] = subject.slice(currentIndex, length); |
490 return result; | 493 return result; |
491 } | 494 } |
492 | 495 |
493 var match = splitMatch(sep, subject, currentIndex, startIndex); | 496 var match = splitMatch(sep, subject, currentIndex, startIndex); |
494 | 497 |
495 if (IS_NULL(match)) { | 498 if (IS_NULL(match)) { |
496 result[result.length] = subject.slice(currentIndex, length); | 499 result[result.length] = subject.slice(currentIndex, length); |
497 return result; | 500 return result; |
498 } | 501 } |
499 | 502 |
500 var endIndex = match[0]; | 503 var endIndex = match[0]; |
501 | 504 |
502 // We ignore a zero-length match at the currentIndex. | 505 // We ignore a zero-length match at the currentIndex. |
503 if (startIndex === endIndex && endIndex === currentIndex) { | 506 if (startIndex === endIndex && endIndex === currentIndex) { |
504 startIndex++; | 507 startIndex++; |
505 continue; | 508 continue; |
506 } | 509 } |
507 | 510 |
508 result[result.length] = match[1]; | 511 result[result.length] = match[1]; |
509 if (result.length === lim) return result; | 512 if (result.length === lim) return result; |
510 | 513 |
511 for (var i = 2; i < match.length; i++) { | 514 for (var i = 2; i < match.length; i++) { |
512 result[result.length] = match[i]; | 515 result[result.length] = match[i]; |
513 if (result.length === lim) return result; | 516 if (result.length === lim) return result; |
514 } | 517 } |
515 | 518 |
516 startIndex = currentIndex = endIndex; | 519 startIndex = currentIndex = endIndex; |
517 } | 520 } |
518 }, DONT_ENUM); | 521 }, DONT_ENUM); |
519 | 522 |
520 | 523 |
521 // ECMA-262 section 15.5.4.14 | 524 // ECMA-262 section 15.5.4.14 |
522 // Helper function used by split. | 525 // Helper function used by split. |
523 function splitMatch(separator, subject, current_index, start_index) { | 526 function splitMatch(separator, subject, current_index, start_index) { |
524 if (IS_REGEXP(separator)) { | 527 if (IS_REGEXP(separator)) { |
525 var ovector = DoRegExpExec(separator, subject, start_index); | 528 var ovector = DoRegExpExec(separator, subject, start_index); |
526 if (ovector == null) return null; | 529 if (ovector == null) return null; |
527 var nof_results = ovector.length >> 1; | 530 var nof_results = ovector.length >> 1; |
528 var result = new $Array(nof_results + 1); | 531 var result = new $Array(nof_results + 1); |
529 result[0] = ovector[1]; | 532 result[0] = ovector[1]; |
530 result[1] = subject.slice(current_index, ovector[0]); | 533 result[1] = subject.slice(current_index, ovector[0]); |
531 for (var i = 1; i < nof_results; i++) { | 534 for (var i = 1; i < nof_results; i++) { |
532 var matching_start = ovector[2*i]; | 535 var matching_start = ovector[2*i]; |
533 var matching_end = ovector[2*i + 1]; | 536 var matching_end = ovector[2*i + 1]; |
534 if (matching_start != -1 && matching_end != -1) { | 537 if (matching_start != -1 && matching_end != -1) { |
535 result[i + 1] = subject.slice(matching_start, matching_end); | 538 result[i + 1] = subject.slice(matching_start, matching_end); |
536 } | 539 } |
537 } | 540 } |
538 return result; | 541 return result; |
539 } | 542 } |
540 | 543 |
541 var separatorIndex = subject.indexOf(separator, start_index); | 544 var separatorIndex = subject.indexOf(separator, start_index); |
542 if (separatorIndex === -1) return null; | 545 if (separatorIndex === -1) return null; |
543 | 546 |
544 return [ separatorIndex + separator.length, subject.slice(current_index, separ
atorIndex) ]; | 547 return [ separatorIndex + separator.length, subject.slice(current_index, separ
atorIndex) ]; |
545 }; | 548 }; |
546 | 549 |
547 | 550 |
548 // ECMA-262 section 15.5.4.15 | 551 // ECMA-262 section 15.5.4.15 |
549 %AddProperty($String.prototype, "substring", function(start, end) { | 552 %AddProperty($String.prototype, "substring", function substring(start, end) { |
550 var s = ToString(this); | 553 var s = ToString(this); |
551 var s_len = s.length; | 554 var s_len = s.length; |
552 var start_i = TO_INTEGER(start); | 555 var start_i = TO_INTEGER(start); |
553 var end_i = s_len; | 556 var end_i = s_len; |
554 if (!IS_UNDEFINED(end)) | 557 if (!IS_UNDEFINED(end)) |
555 end_i = TO_INTEGER(end); | 558 end_i = TO_INTEGER(end); |
556 | 559 |
557 if (start_i < 0) start_i = 0; | 560 if (start_i < 0) start_i = 0; |
558 if (start_i > s_len) start_i = s_len; | 561 if (start_i > s_len) start_i = s_len; |
559 if (end_i < 0) end_i = 0; | 562 if (end_i < 0) end_i = 0; |
560 if (end_i > s_len) end_i = s_len; | 563 if (end_i > s_len) end_i = s_len; |
561 | 564 |
562 if (start_i > end_i) { | 565 if (start_i > end_i) { |
563 var tmp = end_i; | 566 var tmp = end_i; |
564 end_i = start_i; | 567 end_i = start_i; |
565 start_i = tmp; | 568 start_i = tmp; |
566 } | 569 } |
567 | 570 |
568 return SubString(s, start_i, end_i); | 571 return SubString(s, start_i, end_i); |
569 }, DONT_ENUM); | 572 }, DONT_ENUM); |
570 | 573 |
571 | 574 |
572 // This is not a part of ECMA-262. | 575 // This is not a part of ECMA-262. |
573 %AddProperty($String.prototype, "substr", function(start, n) { | 576 %AddProperty($String.prototype, "substr", function substr(start, n) { |
574 var s = ToString(this); | 577 var s = ToString(this); |
575 var len; | 578 var len; |
576 | 579 |
577 // Correct n: If not given, set to string length; if explicitly | 580 // Correct n: If not given, set to string length; if explicitly |
578 // set to undefined, zero, or negative, returns empty string. | 581 // set to undefined, zero, or negative, returns empty string. |
579 if (n === void 0) { | 582 if (n === void 0) { |
580 len = s.length; | 583 len = s.length; |
581 } else { | 584 } else { |
582 len = TO_INTEGER(n); | 585 len = TO_INTEGER(n); |
583 if (len <= 0) return ''; | 586 if (len <= 0) return ''; |
(...skipping 17 matching lines...) Expand all Loading... |
601 } | 604 } |
602 | 605 |
603 var end = start + len; | 606 var end = start + len; |
604 if (end > s.length) end = s.length; | 607 if (end > s.length) end = s.length; |
605 | 608 |
606 return SubString(s, start, end); | 609 return SubString(s, start, end); |
607 }, DONT_ENUM); | 610 }, DONT_ENUM); |
608 | 611 |
609 | 612 |
610 // ECMA-262, 15.5.4.16 | 613 // ECMA-262, 15.5.4.16 |
611 %AddProperty($String.prototype, "toLowerCase", function() { | 614 %AddProperty($String.prototype, "toLowerCase", function toLowerCase() { |
612 return %StringToLowerCase(ToString(this)); | 615 return %StringToLowerCase(ToString(this)); |
613 }, DONT_ENUM); | 616 }, DONT_ENUM); |
614 | 617 |
615 | 618 |
616 // ECMA-262, 15.5.4.17 | 619 // ECMA-262, 15.5.4.17 |
617 %AddProperty($String.prototype, "toLocaleLowerCase", $String.prototype.toLowerCa
se, DONT_ENUM); | 620 %AddProperty($String.prototype, "toLocaleLowerCase", function toLocaleLowerCase(
) { |
| 621 return %StringToLowerCase(ToString(this)); |
| 622 }, DONT_ENUM); |
618 | 623 |
619 | 624 |
620 // ECMA-262, 15.5.4.18 | 625 // ECMA-262, 15.5.4.18 |
621 %AddProperty($String.prototype, "toUpperCase", function() { | 626 %AddProperty($String.prototype, "toUpperCase", function toUpperCase() { |
622 return %StringToUpperCase(ToString(this)); | 627 return %StringToUpperCase(ToString(this)); |
623 }, DONT_ENUM); | 628 }, DONT_ENUM); |
624 | 629 |
625 | 630 |
626 // ECMA-262, 15.5.4.19 | 631 // ECMA-262, 15.5.4.19 |
627 %AddProperty($String.prototype, "toLocaleUpperCase", $String.prototype.toUpperCa
se, DONT_ENUM); | 632 %AddProperty($String.prototype, "toLocaleUpperCase", function toLocaleUpperCase(
) { |
| 633 return %StringToUpperCase(ToString(this)); |
| 634 }, DONT_ENUM); |
628 | 635 |
629 | 636 |
630 // ECMA-262, section 15.5.3.2 | 637 // ECMA-262, section 15.5.3.2 |
631 %AddProperty($String, "fromCharCode", function(code) { | 638 %AddProperty($String, "fromCharCode", function fromCharCode(code) { |
632 var n = %_ArgumentsLength(); | 639 var n = %_ArgumentsLength(); |
633 if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff) | 640 if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff) |
634 | 641 |
635 // NOTE: This is not super-efficient, but it is necessary because we | 642 // NOTE: This is not super-efficient, but it is necessary because we |
636 // want to avoid converting to numbers from within the virtual | 643 // want to avoid converting to numbers from within the virtual |
637 // machine. Maybe we can find another way of doing this? | 644 // machine. Maybe we can find another way of doing this? |
638 var codes = new $Array(n); | 645 var codes = new $Array(n); |
639 for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i)); | 646 for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i)); |
640 return %StringFromCharCodeArray(codes); | 647 return %StringFromCharCodeArray(codes); |
641 }, DONT_ENUM); | 648 }, DONT_ENUM); |
642 | 649 |
643 | 650 |
644 // ECMA-262, section 15.5.4.4 | 651 // ECMA-262, section 15.5.4.4 |
645 function CharAt(pos) { | 652 function charAt(pos) { |
646 var subject = ToString(this); | 653 var subject = ToString(this); |
647 var index = TO_INTEGER(pos); | 654 var index = TO_INTEGER(pos); |
648 if (index >= subject.length || index < 0) return ""; | 655 if (index >= subject.length || index < 0) return ""; |
649 return %CharFromCode(%StringCharCodeAt(subject, index)); | 656 return %CharFromCode(%StringCharCodeAt(subject, index)); |
650 }; | 657 }; |
651 | 658 |
652 %AddProperty($String.prototype, "charAt", CharAt, DONT_ENUM); | 659 %AddProperty($String.prototype, "charAt", charAt, DONT_ENUM); |
653 | 660 |
654 | 661 |
655 // Helper function for very basic XSS protection. | 662 // Helper function for very basic XSS protection. |
656 function HtmlEscape(str) { | 663 function HtmlEscape(str) { |
657 return ToString(str).replace(/</g, "<") | 664 return ToString(str).replace(/</g, "<") |
658 .replace(/>/g, ">") | 665 .replace(/>/g, ">") |
659 .replace(/"/g, """) | 666 .replace(/"/g, """) |
660 .replace(/'/g, "'"); | 667 .replace(/'/g, "'"); |
661 }; | 668 }; |
662 | 669 |
663 | 670 |
664 // Compatibility support for KJS. | 671 // Compatibility support for KJS. |
665 // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js. | 672 // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js. |
666 %AddProperty($String.prototype, "link", function(link) { | 673 %AddProperty($String.prototype, "link", function link(s) { |
667 return "<a href=\"" + HtmlEscape(link) + "\">" + this + "</a>"; | 674 return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>"; |
668 }, DONT_ENUM); | 675 }, DONT_ENUM); |
669 | 676 |
670 | 677 |
671 %AddProperty($String.prototype, "anchor", function(name) { | 678 %AddProperty($String.prototype, "anchor", function anchor(name) { |
672 return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>"; | 679 return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>"; |
673 }, DONT_ENUM); | 680 }, DONT_ENUM); |
674 | 681 |
675 | 682 |
676 %AddProperty($String.prototype, "fontcolor", function(color) { | 683 %AddProperty($String.prototype, "fontcolor", function fontcolor(color) { |
677 return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>"; | 684 return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>"; |
678 }, DONT_ENUM); | 685 }, DONT_ENUM); |
679 | 686 |
680 | 687 |
681 %AddProperty($String.prototype, "fontsize", function(size) { | 688 %AddProperty($String.prototype, "fontsize", function fontsize(size) { |
682 return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>"; | 689 return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>"; |
683 }, DONT_ENUM); | 690 }, DONT_ENUM); |
684 | 691 |
685 | 692 |
686 %AddProperty($String.prototype, "big", function() { | 693 %AddProperty($String.prototype, "big", function big() { |
687 return "<big>" + this + "</big>"; | 694 return "<big>" + this + "</big>"; |
688 }, DONT_ENUM); | 695 }, DONT_ENUM); |
689 | 696 |
690 | 697 |
691 %AddProperty($String.prototype, "blink", function() { | 698 %AddProperty($String.prototype, "blink", function blink() { |
692 return "<blink>" + this + "</blink>"; | 699 return "<blink>" + this + "</blink>"; |
693 }, DONT_ENUM); | 700 }, DONT_ENUM); |
694 | 701 |
695 | 702 |
696 %AddProperty($String.prototype, "bold", function() { | 703 %AddProperty($String.prototype, "bold", function bold() { |
697 return "<b>" + this + "</b>"; | 704 return "<b>" + this + "</b>"; |
698 }, DONT_ENUM); | 705 }, DONT_ENUM); |
699 | 706 |
700 | 707 |
701 %AddProperty($String.prototype, "fixed", function() { | 708 %AddProperty($String.prototype, "fixed", function fixed() { |
702 return "<tt>" + this + "</tt>"; | 709 return "<tt>" + this + "</tt>"; |
703 }, DONT_ENUM); | 710 }, DONT_ENUM); |
704 | 711 |
705 | 712 |
706 %AddProperty($String.prototype, "italics", function() { | 713 %AddProperty($String.prototype, "italics", function italics() { |
707 return "<i>" + this + "</i>"; | 714 return "<i>" + this + "</i>"; |
708 }, DONT_ENUM); | 715 }, DONT_ENUM); |
709 | 716 |
710 | 717 |
711 %AddProperty($String.prototype, "small", function() { | 718 %AddProperty($String.prototype, "small", function small() { |
712 return "<small>" + this + "</small>"; | 719 return "<small>" + this + "</small>"; |
713 }, DONT_ENUM); | 720 }, DONT_ENUM); |
714 | 721 |
715 | 722 |
716 %AddProperty($String.prototype, "strike", function() { | 723 %AddProperty($String.prototype, "strike", function strike() { |
717 return "<strike>" + this + "</strike>"; | 724 return "<strike>" + this + "</strike>"; |
718 }, DONT_ENUM); | 725 }, DONT_ENUM); |
719 | 726 |
720 | 727 |
721 %AddProperty($String.prototype, "sub", function() { | 728 %AddProperty($String.prototype, "sub", function sub() { |
722 return "<sub>" + this + "</sub>"; | 729 return "<sub>" + this + "</sub>"; |
723 }, DONT_ENUM); | 730 }, DONT_ENUM); |
724 | 731 |
725 | 732 |
726 %AddProperty($String.prototype, "sup", function() { | 733 %AddProperty($String.prototype, "sup", function sup() { |
727 return "<sup>" + this + "</sup>"; | 734 return "<sup>" + this + "</sup>"; |
728 }, DONT_ENUM); | 735 }, DONT_ENUM); |
729 | 736 |
730 | 737 |
731 // StringBuilder support. | 738 // StringBuilder support. |
732 | 739 |
733 function StringBuilder() { | 740 function StringBuilder() { |
734 this.elements = new $Array(); | 741 this.elements = new $Array(); |
735 } | 742 } |
736 | 743 |
(...skipping 27 matching lines...) Expand all Loading... |
764 | 771 |
765 | 772 |
766 StringBuilder.prototype.generate = function() { | 773 StringBuilder.prototype.generate = function() { |
767 return %StringBuilderConcat(this.elements, ""); | 774 return %StringBuilderConcat(this.elements, ""); |
768 } | 775 } |
769 | 776 |
770 | 777 |
771 ReplaceResultBuilder.prototype.generate = function() { | 778 ReplaceResultBuilder.prototype.generate = function() { |
772 return %StringBuilderConcat(this.elements, this.special_string); | 779 return %StringBuilderConcat(this.elements, this.special_string); |
773 } | 780 } |
OLD | NEW |