Home | History | Annotate | Download | only in js
      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 
     12 var GlobalString = global.String;
     13 var matchSymbol = utils.ImportNow("match_symbol");
     14 var searchSymbol = utils.ImportNow("search_symbol");
     15 
     16 //-------------------------------------------------------------------
     17 
     18 // ECMA-262, section 15.5.4.6
     19 function 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.
     32 function 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.
     50 function 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
     69 function 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
    111 function HtmlEscape(str) {
    112   return %RegExpInternalReplace(/"/g, TO_STRING(str), "&quot;");
    113 }
    114 
    115 
    116 // ES6 draft, revision 26 (2014-07-18), section B.2.3.2
    117 function 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
    125 function 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
    132 function 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
    139 function 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
    146 function 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
    153 function 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
    161 function 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
    169 function 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
    176 function 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
    183 function 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
    190 function 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
    197 function 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
    204 function 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
    210 function 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
    236 function 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
    261 function 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.
    284 utils.InstallFunctions(GlobalString, DONT_ENUM, [
    285   "raw", StringRaw
    286 ]);
    287 
    288 // Set up the non-enumerable functions on the String prototype object.
    289 utils.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