1// Copyright 2012 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5(function(global, utils) { 6 7%CheckIsBootstrapping(); 8 9// ------------------------------------------------------------------- 10// Imports 11 12var GlobalString = global.String; 13var matchSymbol = utils.ImportNow("match_symbol"); 14var searchSymbol = utils.ImportNow("search_symbol"); 15 16//------------------------------------------------------------------- 17 18// ECMA-262, section 15.5.4.6 19function StringConcat(other /* and more */) { // length == 1 20 "use strict"; 21 CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat"); 22 var s = TO_STRING(this); 23 var len = arguments.length; 24 for (var i = 0; i < len; ++i) { 25 s = s + TO_STRING(arguments[i]); 26 } 27 return s; 28} 29 30 31// ES6 21.1.3.11. 32function StringMatchJS(pattern) { 33 CHECK_OBJECT_COERCIBLE(this, "String.prototype.match"); 34 35 if (!IS_NULL_OR_UNDEFINED(pattern)) { 36 var matcher = pattern[matchSymbol]; 37 if (!IS_UNDEFINED(matcher)) { 38 return %_Call(matcher, pattern, this); 39 } 40 } 41 42 var subject = TO_STRING(this); 43 44 // Equivalent to RegExpCreate (ES#sec-regexpcreate) 45 var regexp = %RegExpCreate(pattern); 46 return regexp[matchSymbol](subject); 47} 48 49// ES6 21.1.3.15. 50function StringSearch(pattern) { 51 CHECK_OBJECT_COERCIBLE(this, "String.prototype.search"); 52 53 if (!IS_NULL_OR_UNDEFINED(pattern)) { 54 var searcher = pattern[searchSymbol]; 55 if (!IS_UNDEFINED(searcher)) { 56 return %_Call(searcher, pattern, this); 57 } 58 } 59 60 var subject = TO_STRING(this); 61 62 // Equivalent to RegExpCreate (ES#sec-regexpcreate) 63 var regexp = %RegExpCreate(pattern); 64 return %_Call(regexp[searchSymbol], regexp, subject); 65} 66 67 68// ECMA-262 section 15.5.4.13 69function StringSlice(start, end) { 70 CHECK_OBJECT_COERCIBLE(this, "String.prototype.slice"); 71 72 var s = TO_STRING(this); 73 var s_len = s.length; 74 var start_i = TO_INTEGER(start); 75 var end_i = s_len; 76 if (!IS_UNDEFINED(end)) { 77 end_i = TO_INTEGER(end); 78 } 79 80 if (start_i < 0) { 81 start_i += s_len; 82 if (start_i < 0) { 83 start_i = 0; 84 } 85 } else { 86 if (start_i > s_len) { 87 return ''; 88 } 89 } 90 91 if (end_i < 0) { 92 end_i += s_len; 93 if (end_i < 0) { 94 return ''; 95 } 96 } else { 97 if (end_i > s_len) { 98 end_i = s_len; 99 } 100 } 101 102 if (end_i <= start_i) { 103 return ''; 104 } 105 106 return %_SubString(s, start_i, end_i); 107} 108 109 110// ES6 draft, revision 26 (2014-07-18), section B.2.3.2.1 111function HtmlEscape(str) { 112 return %RegExpInternalReplace(/"/g, TO_STRING(str), """); 113} 114 115 116// ES6 draft, revision 26 (2014-07-18), section B.2.3.2 117function StringAnchor(name) { 118 CHECK_OBJECT_COERCIBLE(this, "String.prototype.anchor"); 119 return "<a name=\"" + HtmlEscape(name) + "\">" + TO_STRING(this) + 120 "</a>"; 121} 122 123 124// ES6 draft, revision 26 (2014-07-18), section B.2.3.3 125function StringBig() { 126 CHECK_OBJECT_COERCIBLE(this, "String.prototype.big"); 127 return "<big>" + TO_STRING(this) + "</big>"; 128} 129 130 131// ES6 draft, revision 26 (2014-07-18), section B.2.3.4 132function StringBlink() { 133 CHECK_OBJECT_COERCIBLE(this, "String.prototype.blink"); 134 return "<blink>" + TO_STRING(this) + "</blink>"; 135} 136 137 138// ES6 draft, revision 26 (2014-07-18), section B.2.3.5 139function StringBold() { 140 CHECK_OBJECT_COERCIBLE(this, "String.prototype.bold"); 141 return "<b>" + TO_STRING(this) + "</b>"; 142} 143 144 145// ES6 draft, revision 26 (2014-07-18), section B.2.3.6 146function StringFixed() { 147 CHECK_OBJECT_COERCIBLE(this, "String.prototype.fixed"); 148 return "<tt>" + TO_STRING(this) + "</tt>"; 149} 150 151 152// ES6 draft, revision 26 (2014-07-18), section B.2.3.7 153function StringFontcolor(color) { 154 CHECK_OBJECT_COERCIBLE(this, "String.prototype.fontcolor"); 155 return "<font color=\"" + HtmlEscape(color) + "\">" + TO_STRING(this) + 156 "</font>"; 157} 158 159 160// ES6 draft, revision 26 (2014-07-18), section B.2.3.8 161function StringFontsize(size) { 162 CHECK_OBJECT_COERCIBLE(this, "String.prototype.fontsize"); 163 return "<font size=\"" + HtmlEscape(size) + "\">" + TO_STRING(this) + 164 "</font>"; 165} 166 167 168// ES6 draft, revision 26 (2014-07-18), section B.2.3.9 169function StringItalics() { 170 CHECK_OBJECT_COERCIBLE(this, "String.prototype.italics"); 171 return "<i>" + TO_STRING(this) + "</i>"; 172} 173 174 175// ES6 draft, revision 26 (2014-07-18), section B.2.3.10 176function StringLink(s) { 177 CHECK_OBJECT_COERCIBLE(this, "String.prototype.link"); 178 return "<a href=\"" + HtmlEscape(s) + "\">" + TO_STRING(this) + "</a>"; 179} 180 181 182// ES6 draft, revision 26 (2014-07-18), section B.2.3.11 183function StringSmall() { 184 CHECK_OBJECT_COERCIBLE(this, "String.prototype.small"); 185 return "<small>" + TO_STRING(this) + "</small>"; 186} 187 188 189// ES6 draft, revision 26 (2014-07-18), section B.2.3.12 190function StringStrike() { 191 CHECK_OBJECT_COERCIBLE(this, "String.prototype.strike"); 192 return "<strike>" + TO_STRING(this) + "</strike>"; 193} 194 195 196// ES6 draft, revision 26 (2014-07-18), section B.2.3.13 197function StringSub() { 198 CHECK_OBJECT_COERCIBLE(this, "String.prototype.sub"); 199 return "<sub>" + TO_STRING(this) + "</sub>"; 200} 201 202 203// ES6 draft, revision 26 (2014-07-18), section B.2.3.14 204function StringSup() { 205 CHECK_OBJECT_COERCIBLE(this, "String.prototype.sup"); 206 return "<sup>" + TO_STRING(this) + "</sup>"; 207} 208 209// ES6, section 21.1.3.13 210function StringRepeat(count) { 211 CHECK_OBJECT_COERCIBLE(this, "String.prototype.repeat"); 212 213 var s = TO_STRING(this); 214 var n = TO_INTEGER(count); 215 216 if (n < 0 || n === INFINITY) throw %make_range_error(kInvalidCountValue); 217 218 // Early return to allow an arbitrarily-large repeat of the empty string. 219 if (s.length === 0) return ""; 220 221 // The maximum string length is stored in a smi, so a longer repeat 222 // must result in a range error. 223 if (n > %_MaxSmi()) throw %make_range_error(kInvalidCountValue); 224 225 var r = ""; 226 while (true) { 227 if (n & 1) r += s; 228 n >>= 1; 229 if (n === 0) return r; 230 s += s; 231 } 232} 233 234 235// ES6 Draft 05-22-2014, section 21.1.3.3 236function StringCodePointAt(pos) { 237 CHECK_OBJECT_COERCIBLE(this, "String.prototype.codePointAt"); 238 239 var string = TO_STRING(this); 240 var size = string.length; 241 pos = TO_INTEGER(pos); 242 if (pos < 0 || pos >= size) { 243 return UNDEFINED; 244 } 245 var first = %_StringCharCodeAt(string, pos); 246 if (first < 0xD800 || first > 0xDBFF || pos + 1 == size) { 247 return first; 248 } 249 var second = %_StringCharCodeAt(string, pos + 1); 250 if (second < 0xDC00 || second > 0xDFFF) { 251 return first; 252 } 253 return (first - 0xD800) * 0x400 + second + 0x2400; 254} 255 256 257// ------------------------------------------------------------------- 258// String methods related to templates 259 260// ES6 Draft 03-17-2015, section 21.1.2.4 261function StringRaw(callSite) { 262 "use strict"; 263 var numberOfSubstitutions = arguments.length; 264 var cooked = TO_OBJECT(callSite); 265 var raw = TO_OBJECT(cooked.raw); 266 var literalSegments = TO_LENGTH(raw.length); 267 if (literalSegments <= 0) return ""; 268 269 var result = TO_STRING(raw[0]); 270 271 for (var i = 1; i < literalSegments; ++i) { 272 if (i < numberOfSubstitutions) { 273 result += TO_STRING(arguments[i]); 274 } 275 result += TO_STRING(raw[i]); 276 } 277 278 return result; 279} 280 281// ------------------------------------------------------------------- 282 283// Set up the non-enumerable functions on the String object. 284utils.InstallFunctions(GlobalString, DONT_ENUM, [ 285 "raw", StringRaw 286]); 287 288// Set up the non-enumerable functions on the String prototype object. 289utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [ 290 "codePointAt", StringCodePointAt, 291 "concat", StringConcat, 292 "match", StringMatchJS, 293 "repeat", StringRepeat, 294 "search", StringSearch, 295 "slice", StringSlice, 296 297 "link", StringLink, 298 "anchor", StringAnchor, 299 "fontcolor", StringFontcolor, 300 "fontsize", StringFontsize, 301 "big", StringBig, 302 "blink", StringBlink, 303 "bold", StringBold, 304 "fixed", StringFixed, 305 "italics", StringItalics, 306 "small", StringSmall, 307 "strike", StringStrike, 308 "sub", StringSub, 309 "sup", StringSup 310]); 311 312}) 313