Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 // This file relies on the fact that the following declaration has been made | 7 // This file relies on the fact that the following declaration has been made |
| 8 // in runtime.js: | 8 // in runtime.js: |
| 9 // var $String = global.String; | 9 // var $String = global.String; |
| 10 // var $Array = global.Array; | 10 // var $Array = global.Array; |
| 11 | 11 |
| 12 // ------------------------------------------------------------------- | 12 // ------------------------------------------------------------------- |
| 13 | 13 |
| 14 // ES6 draft 01-20-14, section 21.1.3.13 | 14 // ES6 draft 01-20-14, section 21.1.3.13 |
| 15 function StringRepeat(count) { | 15 function StringRepeat(count) { |
| 16 CHECK_OBJECT_COERCIBLE(this, "String.prototype.repeat"); | 16 CHECK_OBJECT_COERCIBLE(this, "String.prototype.repeat"); |
| 17 | 17 |
| 18 var s = TO_STRING_INLINE(this); | 18 var s = TO_STRING_INLINE(this); |
| 19 var n = ToInteger(count); | 19 var n = ToInteger(count); |
| 20 if (n < 0 || !NUMBER_IS_FINITE(n)) { | 20 if (n < 0 || !NUMBER_IS_FINITE(n)) { |
| 21 throw MakeRangeError("invalid_count_value", []); | 21 throw MakeRangeError("invalid_count_value", []); |
| 22 } | 22 } |
| 23 | 23 |
| 24 var elements = new InternalArray(n); | 24 if (n < 1) return ''; |
|
Michael Starzinger
2014/07/28 11:13:52
This special case is not needed if comment below i
| |
| 25 for (var i = 0; i < n; i++) { | 25 |
| 26 elements[i] = s; | 26 // Optimized O(log N) algorithm, without the added overhead of an extra array |
|
Michael Starzinger
2014/07/28 11:13:51
nit: Let's drop (at least) the second half of the
| |
| 27 var res = ''; | |
| 28 | |
| 29 while (n > 1) { | |
|
Michael Starzinger
2014/07/28 11:13:51
If we change the predicate to be "n > 0" most spec
| |
| 30 if (n & 1) res += s; | |
| 31 n >>= 1; | |
| 32 s += s; | |
| 27 } | 33 } |
| 28 | 34 return res + s; |
|
Michael Starzinger
2014/07/28 11:13:51
This addition is not needed if comment above is ad
| |
| 29 return %StringBuilderConcat(elements, n, ""); | |
| 30 } | 35 } |
| 31 | 36 |
| 32 | 37 |
| 33 // ES6 draft 04-05-14, section 21.1.3.18 | 38 // ES6 draft 04-05-14, section 21.1.3.18 |
| 34 function StringStartsWith(searchString /* position */) { // length == 1 | 39 function StringStartsWith(searchString /* position */) { // length == 1 |
| 35 CHECK_OBJECT_COERCIBLE(this, "String.prototype.startsWith"); | 40 CHECK_OBJECT_COERCIBLE(this, "String.prototype.startsWith"); |
| 36 | 41 |
| 37 var s = TO_STRING_INLINE(this); | 42 var s = TO_STRING_INLINE(this); |
| 38 | 43 |
| 39 if (IS_REGEXP(searchString)) { | 44 if (IS_REGEXP(searchString)) { |
| 40 throw MakeTypeError("first_argument_not_regexp", | 45 throw MakeTypeError("first_argument_not_regexp", |
| 41 ["String.prototype.startsWith"]); | 46 ["String.prototype.startsWith"]); |
| 42 } | 47 } |
| 43 | 48 |
| 44 var ss = TO_STRING_INLINE(searchString); | 49 var ss = TO_STRING_INLINE(searchString); |
| 45 var pos = 0; | 50 var pos = 0; |
| 46 if (%_ArgumentsLength() > 1) { | 51 if (%_ArgumentsLength() > 1) { |
| 47 pos = %_Arguments(1); // position | 52 pos = %_Arguments(1); // position |
| 48 pos = ToInteger(pos); | 53 pos = ToInteger(pos); |
| 49 } | 54 } |
| 50 | 55 |
| 51 var s_len = s.length; | 56 var s_len = s.length; |
| 52 var start = MathMin(MathMax(pos, 0), s_len); | 57 var start = MathMin(MathMax(pos, 0), s_len); |
| 53 var ss_len = ss.length; | 58 if (ss.length + start > s_len) { |
| 54 if (ss_len + start > s_len) { | |
| 55 return false; | 59 return false; |
| 56 } | 60 } |
| 57 | 61 |
| 58 return %StringIndexOf(s, ss, start) === start; | 62 return %StringIndexOf(s, ss, start) === start; |
| 59 } | 63 } |
| 60 | 64 |
| 61 | 65 |
| 62 // ES6 draft 04-05-14, section 21.1.3.7 | 66 // ES6 draft 04-05-14, section 21.1.3.7 |
| 63 function StringEndsWith(searchString /* position */) { // length == 1 | 67 function StringEndsWith(searchString /* position */) { // length == 1 |
| 64 CHECK_OBJECT_COERCIBLE(this, "String.prototype.endsWith"); | 68 CHECK_OBJECT_COERCIBLE(this, "String.prototype.endsWith"); |
| 65 | 69 |
| 66 var s = TO_STRING_INLINE(this); | 70 var s = TO_STRING_INLINE(this); |
| 67 | 71 |
| 68 if (IS_REGEXP(searchString)) { | 72 if (IS_REGEXP(searchString)) { |
| 69 throw MakeTypeError("first_argument_not_regexp", | 73 throw MakeTypeError("first_argument_not_regexp", |
| 70 ["String.prototype.endsWith"]); | 74 ["String.prototype.endsWith"]); |
| 71 } | 75 } |
| 72 | 76 |
| 73 var ss = TO_STRING_INLINE(searchString); | 77 var ss = TO_STRING_INLINE(searchString); |
| 74 var s_len = s.length; | 78 var s_len = s.length; |
| 75 var pos = s_len; | 79 var pos = s_len; |
| 76 if (%_ArgumentsLength() > 1) { | 80 if (%_ArgumentsLength() > 1) { |
| 77 var arg = %_Arguments(1); // position | 81 var arg = %_Arguments(1); // position |
| 78 if (!IS_UNDEFINED(arg)) { | 82 if (!IS_UNDEFINED(arg)) { |
| 79 pos = ToInteger(arg); | 83 pos = ToInteger(arg); |
| 80 } | 84 } |
| 81 } | 85 } |
| 82 | 86 |
| 83 var end = MathMin(MathMax(pos, 0), s_len); | 87 var end = MathMin(MathMax(pos, 0), s_len); |
| 84 var ss_len = ss.length; | 88 var start = end - ss.length; |
| 85 var start = end - ss_len; | |
| 86 if (start < 0) { | 89 if (start < 0) { |
| 87 return false; | 90 return false; |
| 88 } | 91 } |
| 89 | 92 |
| 90 return %StringLastIndexOf(s, ss, start) === start; | 93 return %StringLastIndexOf(s, ss, start) === start; |
| 91 } | 94 } |
| 92 | 95 |
| 93 | 96 |
| 94 // ES6 draft 04-05-14, section 21.1.3.6 | 97 // ES6 draft 04-05-14, section 21.1.3.6 |
| 95 function StringContains(searchString /* position */) { // length == 1 | 98 function StringContains(searchString /* position */) { // length == 1 |
| 96 CHECK_OBJECT_COERCIBLE(this, "String.prototype.contains"); | 99 CHECK_OBJECT_COERCIBLE(this, "String.prototype.contains"); |
| 97 | 100 |
| 98 var s = TO_STRING_INLINE(this); | 101 var s = TO_STRING_INLINE(this); |
| 99 | 102 |
| 100 if (IS_REGEXP(searchString)) { | 103 if (IS_REGEXP(searchString)) { |
| 101 throw MakeTypeError("first_argument_not_regexp", | 104 throw MakeTypeError("first_argument_not_regexp", |
| 102 ["String.prototype.contains"]); | 105 ["String.prototype.contains"]); |
| 103 } | 106 } |
| 104 | 107 |
| 105 var ss = TO_STRING_INLINE(searchString); | 108 var ss = TO_STRING_INLINE(searchString); |
| 106 var pos = 0; | 109 var pos = 0; |
| 107 if (%_ArgumentsLength() > 1) { | 110 if (%_ArgumentsLength() > 1) { |
| 108 pos = %_Arguments(1); // position | 111 pos = %_Arguments(1); // position |
| 109 pos = ToInteger(pos); | 112 pos = ToInteger(pos); |
| 110 } | 113 } |
| 111 | 114 |
| 112 var s_len = s.length; | 115 var s_len = s.length; |
| 113 var start = MathMin(MathMax(pos, 0), s_len); | 116 var start = MathMin(MathMax(pos, 0), s_len); |
| 114 var ss_len = ss.length; | 117 if (ss.length + start > s_len) { |
| 115 if (ss_len + start > s_len) { | |
| 116 return false; | 118 return false; |
| 117 } | 119 } |
| 118 | 120 |
| 119 return %StringIndexOf(s, ss, start) !== -1; | 121 return %StringIndexOf(s, ss, start) !== -1; |
| 120 } | 122 } |
| 121 | 123 |
| 122 | 124 |
| 123 // ------------------------------------------------------------------- | 125 // ------------------------------------------------------------------- |
| 124 | 126 |
| 125 function ExtendStringPrototype() { | 127 function ExtendStringPrototype() { |
| 126 %CheckIsBootstrapping(); | 128 %CheckIsBootstrapping(); |
| 127 | 129 |
| 128 // Set up the non-enumerable functions on the String prototype object. | 130 // Set up the non-enumerable functions on the String prototype object. |
| 129 InstallFunctions($String.prototype, DONT_ENUM, $Array( | 131 InstallFunctions($String.prototype, DONT_ENUM, $Array( |
| 130 "repeat", StringRepeat, | 132 "repeat", StringRepeat, |
| 131 "startsWith", StringStartsWith, | 133 "startsWith", StringStartsWith, |
| 132 "endsWith", StringEndsWith, | 134 "endsWith", StringEndsWith, |
| 133 "contains", StringContains | 135 "contains", StringContains |
| 134 )); | 136 )); |
| 135 } | 137 } |
| 136 | 138 |
| 137 ExtendStringPrototype(); | 139 ExtendStringPrototype(); |
| OLD | NEW |