1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 function StringProtoHasNoMatch() {
6 var ObjectProto = GetBuiltinPrototype("Object");
7 var StringProto = GetBuiltinPrototype("String");
8 if (!ObjectHasPrototype(StringProto, ObjectProto)) {
11 return !(GetBuiltinSymbol("match") in StringProto);
14 function IsStringMatchOptimizable() {
15 var RegExpProto = GetBuiltinPrototype("RegExp");
16 // If RegExpPrototypeOptimizable succeeds, `exec` and `@@match` are
17 // guaranteed to be data properties.
19 RegExpPrototypeOptimizable(RegExpProto) &&
20 RegExpProto.exec === RegExp_prototype_Exec &&
21 RegExpProto[GetBuiltinSymbol("match")] === RegExpMatch
25 function ThrowIncompatibleMethod(name, thisv) {
26 ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "String", name, ToString(thisv));
29 // ES 2016 draft Mar 25, 2016 21.1.3.11.
30 function String_match(regexp) {
32 if (IsNullOrUndefined(this)) {
33 ThrowIncompatibleMethod("match", this);
37 var isPatternString = typeof regexp === "string";
39 !(isPatternString && StringProtoHasNoMatch()) &&
40 !IsNullOrUndefined(regexp)
43 var matcher = GetMethod(regexp, GetBuiltinSymbol("match"));
46 if (matcher !== undefined) {
47 return callContentFunction(matcher, regexp, this);
52 var S = ToString(this);
54 if (isPatternString && IsStringMatchOptimizable()) {
55 var flatResult = FlatStringMatch(S, regexp);
56 if (flatResult !== undefined) {
62 var rx = RegExpCreate(regexp);
64 // Step 5 (optimized case).
65 if (IsStringMatchOptimizable()) {
66 return RegExpMatcher(rx, S, 0);
70 return callContentFunction(GetMethod(rx, GetBuiltinSymbol("match")), rx, S);
73 // String.prototype.matchAll proposal.
75 // String.prototype.matchAll ( regexp )
76 function String_matchAll(regexp) {
78 if (IsNullOrUndefined(this)) {
79 ThrowIncompatibleMethod("matchAll", this);
83 if (!IsNullOrUndefined(regexp)) {
85 if (IsRegExp(regexp)) {
87 var flags = regexp.flags;
90 if (IsNullOrUndefined(flags)) {
91 ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL);
95 if (!callFunction(std_String_includes, ToString(flags), "g")) {
96 ThrowTypeError(JSMSG_REQUIRES_GLOBAL_REGEXP, "matchAll");
101 var matcher = GetMethod(regexp, GetBuiltinSymbol("matchAll"));
104 if (matcher !== undefined) {
105 return callContentFunction(matcher, regexp, this);
110 var string = ToString(this);
113 var rx = RegExpCreate(regexp, "g");
116 return callContentFunction(
117 GetMethod(rx, GetBuiltinSymbol("matchAll")),
124 * A helper function implementing the logic for both String.prototype.padStart
125 * and String.prototype.padEnd as described in ES7 Draft March 29, 2016
127 function String_pad(maxLength, fillString, padEnd) {
129 if (IsNullOrUndefined(this)) {
130 ThrowIncompatibleMethod(padEnd ? "padEnd" : "padStart", this);
134 var str = ToString(this);
137 var intMaxLength = ToLength(maxLength);
138 var strLen = str.length;
141 if (intMaxLength <= strLen) {
146 assert(fillString !== undefined, "never called when fillString is undefined");
147 var filler = ToString(fillString);
154 // Throw an error if the final string length exceeds the maximum string
155 // length. Perform this check early so we can use int32 operations below.
156 if (intMaxLength > MAX_STRING_LENGTH) {
157 ThrowRangeError(JSMSG_RESULTING_STRING_TOO_LARGE);
161 var fillLen = intMaxLength - strLen;
164 // Perform an int32 division to ensure String_repeat is not called with a
165 // double to avoid repeated bailouts in ToInteger.
166 var truncatedStringFiller = callFunction(
169 (fillLen / filler.length) | 0
172 truncatedStringFiller += Substring(filler, 0, fillLen % filler.length);
175 if (padEnd === true) {
176 return str + truncatedStringFiller;
178 return truncatedStringFiller + str;
181 function String_pad_start(maxLength, fillString = " ") {
182 return callFunction(String_pad, this, maxLength, fillString, false);
185 function String_pad_end(maxLength, fillString = " ") {
186 return callFunction(String_pad, this, maxLength, fillString, true);
189 function StringProtoHasNoReplace() {
190 var ObjectProto = GetBuiltinPrototype("Object");
191 var StringProto = GetBuiltinPrototype("String");
192 if (!ObjectHasPrototype(StringProto, ObjectProto)) {
195 return !(GetBuiltinSymbol("replace") in StringProto);
198 // A thin wrapper to call SubstringKernel with int32-typed arguments.
199 // Caller should check the range of |from| and |length|.
200 function Substring(str, from, length) {
201 assert(typeof str === "string", "|str| should be a string");
204 "coercing |from| into int32 should not change the value"
207 (length | 0) === length,
208 "coercing |length| into int32 should not change the value"
211 return SubstringKernel(
213 std_Math_max(from, 0) | 0,
214 std_Math_max(length, 0) | 0
218 // ES 2016 draft Mar 25, 2016 21.1.3.14.
219 function String_replace(searchValue, replaceValue) {
221 if (IsNullOrUndefined(this)) {
222 ThrowIncompatibleMethod("replace", this);
227 !(typeof searchValue === "string" && StringProtoHasNoReplace()) &&
228 !IsNullOrUndefined(searchValue)
231 var replacer = GetMethod(searchValue, GetBuiltinSymbol("replace"));
234 if (replacer !== undefined) {
235 return callContentFunction(replacer, searchValue, this, replaceValue);
240 var string = ToString(this);
243 var searchString = ToString(searchValue);
245 if (typeof replaceValue === "string") {
246 // Steps 6-12: Optimized for string case.
247 return StringReplaceString(string, searchString, replaceValue);
251 if (!IsCallable(replaceValue)) {
253 return StringReplaceString(string, searchString, ToString(replaceValue));
257 var pos = callFunction(std_String_indexOf, string, searchString);
263 var replStr = ToString(
264 callContentFunction(replaceValue, undefined, searchString, pos, string)
268 var tailPos = pos + searchString.length;
275 newString = Substring(string, 0, pos);
278 newString += replStr;
279 var stringLength = string.length;
280 if (tailPos < stringLength) {
281 newString += Substring(string, tailPos, stringLength - tailPos);
288 // String.prototype.replaceAll (Stage 3 proposal)
289 // https://tc39.es/proposal-string-replaceall/
291 // String.prototype.replaceAll ( searchValue, replaceValue )
292 function String_replaceAll(searchValue, replaceValue) {
294 if (IsNullOrUndefined(this)) {
295 ThrowIncompatibleMethod("replaceAll", this);
299 if (!IsNullOrUndefined(searchValue)) {
301 if (IsRegExp(searchValue)) {
303 var flags = searchValue.flags;
306 if (IsNullOrUndefined(flags)) {
307 ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL);
311 if (!callFunction(std_String_includes, ToString(flags), "g")) {
312 ThrowTypeError(JSMSG_REQUIRES_GLOBAL_REGEXP, "replaceAll");
317 var replacer = GetMethod(searchValue, GetBuiltinSymbol("replace"));
320 if (replacer !== undefined) {
321 return callContentFunction(replacer, searchValue, this, replaceValue);
326 var string = ToString(this);
329 var searchString = ToString(searchValue);
332 if (!IsCallable(replaceValue)) {
334 return StringReplaceAllString(string, searchString, ToString(replaceValue));
338 var searchLength = searchString.length;
341 var advanceBy = std_Math_max(1, searchLength);
343 // Step 9 (not needed in this implementation).
346 var endOfLastMatch = 0;
356 // StringIndexOf doesn't clamp the |position| argument to the input
357 // string length, i.e. |StringIndexOf("abc", "", 4)| returns -1,
358 // whereas |"abc".indexOf("", 4)| returns 3. That means we need to
359 // exit the loop when |nextPosition| is smaller than |position| and
360 // not just when |nextPosition| is -1.
361 var nextPosition = callFunction(
367 if (nextPosition < position) {
370 position = nextPosition;
373 var replacement = ToString(
383 // Step 14.b (not applicable).
386 var stringSlice = Substring(
389 position - endOfLastMatch
393 result += stringSlice + replacement;
396 endOfLastMatch = position + searchLength;
399 position += advanceBy;
403 if (endOfLastMatch < string.length) {
405 result += Substring(string, endOfLastMatch, string.length - endOfLastMatch);
412 function StringProtoHasNoSearch() {
413 var ObjectProto = GetBuiltinPrototype("Object");
414 var StringProto = GetBuiltinPrototype("String");
415 if (!ObjectHasPrototype(StringProto, ObjectProto)) {
418 return !(GetBuiltinSymbol("search") in StringProto);
421 function IsStringSearchOptimizable() {
422 var RegExpProto = GetBuiltinPrototype("RegExp");
423 // If RegExpPrototypeOptimizable succeeds, `exec` and `@@search` are
424 // guaranteed to be data properties.
426 RegExpPrototypeOptimizable(RegExpProto) &&
427 RegExpProto.exec === RegExp_prototype_Exec &&
428 RegExpProto[GetBuiltinSymbol("search")] === RegExpSearch
432 // ES 2016 draft Mar 25, 2016 21.1.3.15.
433 function String_search(regexp) {
435 if (IsNullOrUndefined(this)) {
436 ThrowIncompatibleMethod("search", this);
440 var isPatternString = typeof regexp === "string";
442 !(isPatternString && StringProtoHasNoSearch()) &&
443 !IsNullOrUndefined(regexp)
446 var searcher = GetMethod(regexp, GetBuiltinSymbol("search"));
449 if (searcher !== undefined) {
450 return callContentFunction(searcher, regexp, this);
455 var string = ToString(this);
457 if (isPatternString && IsStringSearchOptimizable()) {
458 var flatResult = FlatStringSearch(string, regexp);
459 if (flatResult !== -2) {
465 var rx = RegExpCreate(regexp);
468 return callContentFunction(
469 GetMethod(rx, GetBuiltinSymbol("search")),
475 function StringProtoHasNoSplit() {
476 var ObjectProto = GetBuiltinPrototype("Object");
477 var StringProto = GetBuiltinPrototype("String");
478 if (!ObjectHasPrototype(StringProto, ObjectProto)) {
481 return !(GetBuiltinSymbol("split") in StringProto);
484 // ES 2016 draft Mar 25, 2016 21.1.3.17.
485 function String_split(separator, limit) {
487 if (IsNullOrUndefined(this)) {
488 ThrowIncompatibleMethod("split", this);
491 // Optimized path for string.split(string), especially when both strings
492 // are constants. Following sequence of if's cannot be put together in
493 // order that IonMonkey sees the constant if present (bug 1246141).
494 if (typeof this === "string") {
495 if (StringProtoHasNoSplit()) {
496 if (typeof separator === "string") {
497 if (limit === undefined) {
498 // inlineConstantStringSplitString needs both arguments to
499 // be MConstant, so pass them directly.
500 return StringSplitString(this, separator);
508 !(typeof separator === "string" && StringProtoHasNoSplit()) &&
509 !IsNullOrUndefined(separator)
512 var splitter = GetMethod(separator, GetBuiltinSymbol("split"));
515 if (splitter !== undefined) {
516 return callContentFunction(splitter, separator, this, limit);
521 var S = ToString(this);
525 if (limit !== undefined) {
526 var lim = limit >>> 0;
529 R = ToString(separator);
537 if (separator === undefined) {
541 // Steps 4, 8, 12-18.
542 return StringSplitStringLimit(S, R, lim);
546 R = ToString(separator);
549 if (separator === undefined) {
554 // Steps 4, 8, 12-18.
555 return StringSplitString(S, R);
558 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
559 // 21.1.3.22 String.prototype.substring ( start, end )
560 function String_substring(start, end) {
562 if (IsNullOrUndefined(this)) {
563 ThrowIncompatibleMethod("substring", this);
567 var str = ToString(this);
570 var len = str.length;
573 var intStart = ToInteger(start);
576 var intEnd = end === undefined ? len : ToInteger(end);
579 var finalStart = std_Math_min(std_Math_max(intStart, 0), len);
582 var finalEnd = std_Math_min(std_Math_max(intEnd, 0), len);
585 var from = std_Math_min(finalStart, finalEnd);
588 var to = std_Math_max(finalStart, finalEnd);
591 // While |from| and |to - from| are bounded to the length of |str| and this
592 // and thus definitely in the int32 range, they can still be typed as
593 // double. Eagerly truncate since SubstringKernel only accepts int32.
594 return SubstringKernel(str, from | 0, (to - from) | 0);
596 SetIsInlinableLargeFunction(String_substring);
598 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
599 // B.2.3.1 String.prototype.substr ( start, length )
600 function String_substr(start, length) {
602 if (IsNullOrUndefined(this)) {
603 ThrowIncompatibleMethod("substr", this);
607 var str = ToString(this);
610 var intStart = ToInteger(start);
613 var size = str.length;
614 // Use |size| instead of +Infinity to avoid performing calculations with
615 // doubles. (The result is the same either way.)
616 var end = length === undefined ? size : ToInteger(length);
620 intStart = std_Math_max(intStart + size, 0);
622 // Restrict the input range to allow better Ion optimizations.
623 intStart = std_Math_min(intStart, size);
627 var resultLength = std_Math_min(std_Math_max(end, 0), size - intStart);
631 0 <= resultLength && resultLength <= size - intStart,
632 "resultLength is a valid substring length value"
636 // While |intStart| and |resultLength| are bounded to the length of |str|
637 // and thus definitely in the int32 range, they can still be typed as
638 // double. Eagerly truncate since SubstringKernel only accepts int32.
639 return SubstringKernel(str, intStart | 0, resultLength | 0);
641 SetIsInlinableLargeFunction(String_substr);
643 // ES2021 draft rev 12a546b92275a0e2f834017db2727bb9c6f6c8fd
644 // 21.1.3.4 String.prototype.concat ( ...args )
645 // Note: String.prototype.concat.length is 1.
646 function String_concat(arg1) {
648 if (IsNullOrUndefined(this)) {
649 ThrowIncompatibleMethod("concat", this);
653 var str = ToString(this);
655 // Specialize for the most common number of arguments for better inlining.
656 if (ArgumentsLength() === 0) {
659 if (ArgumentsLength() === 1) {
660 return str + ToString(GetArgument(0));
662 if (ArgumentsLength() === 2) {
663 return str + ToString(GetArgument(0)) + ToString(GetArgument(1));
666 // Step 3. (implicit)
671 for (var i = 0; i < ArgumentsLength(); i++) {
673 var nextString = ToString(GetArgument(i));
675 result += nextString;
682 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
683 // 21.1.3.19 String.prototype.slice ( start, end )
684 function String_slice(start, end) {
686 if (IsNullOrUndefined(this)) {
687 ThrowIncompatibleMethod("slice", this);
691 var str = ToString(this);
694 var len = str.length;
697 var intStart = ToInteger(start);
700 var intEnd = end === undefined ? len : ToInteger(end);
705 ? std_Math_max(len + intStart, 0)
706 : std_Math_min(intStart, len);
710 intEnd < 0 ? std_Math_max(len + intEnd, 0) : std_Math_min(intEnd, len);
713 var span = std_Math_max(to - from, 0);
716 // While |from| and |span| are bounded to the length of |str|
717 // and thus definitely in the int32 range, they can still be typed as
718 // double. Eagerly truncate since SubstringKernel only accepts int32.
719 return SubstringKernel(str, from | 0, span | 0);
721 SetIsInlinableLargeFunction(String_slice);
723 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
724 // 21.1.3.16 String.prototype.repeat ( count )
725 function String_repeat(count) {
727 if (IsNullOrUndefined(this)) {
728 ThrowIncompatibleMethod("repeat", this);
732 var S = ToString(this);
735 var n = ToInteger(count);
739 ThrowRangeError(JSMSG_NEGATIVE_REPETITION_COUNT);
743 // Inverted condition to handle |Infinity * 0 = NaN| correctly.
744 if (!(n * S.length <= MAX_STRING_LENGTH)) {
745 ThrowRangeError(JSMSG_RESULTING_STRING_TOO_LARGE);
748 // Communicate |n|'s possible range to the compiler. We actually use
749 // MAX_STRING_LENGTH + 1 as range because that's a valid bit mask. That's
750 // fine because it's only used as optimization hint.
752 TO_INT32(MAX_STRING_LENGTH + 1) === MAX_STRING_LENGTH + 1,
753 "MAX_STRING_LENGTH + 1 must fit in int32"
756 ((MAX_STRING_LENGTH + 1) & (MAX_STRING_LENGTH + 2)) === 0,
757 "MAX_STRING_LENGTH + 1 can be used as a bitmask"
759 n = n & (MAX_STRING_LENGTH + 1);
777 // ES6 draft specification, section 21.1.3.27, version 2013-09-27.
778 function String_iterator() {
780 if (IsNullOrUndefined(this)) {
782 JSMSG_INCOMPATIBLE_PROTO2,
790 var S = ToString(this);
793 var iterator = NewStringIterator();
794 UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_TARGET, S);
795 UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, 0);
799 function StringIteratorNext() {
801 if (!IsObject(obj) || (obj = GuardToStringIterator(obj)) === null) {
803 CallStringIteratorMethodIfWrapped,
809 var S = UnsafeGetStringFromReservedSlot(obj, ITERATOR_SLOT_TARGET);
810 // We know that JSString::MAX_LENGTH <= INT32_MAX (and assert this in
811 // SelfHostring.cpp) so our current index can never be anything other than
813 var index = UnsafeGetInt32FromReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX);
815 var result = { value: undefined, done: false };
822 var codePoint = callFunction(std_String_codePointAt, S, index);
823 var charCount = 1 + (codePoint > 0xffff);
825 UnsafeSetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
827 result.value = callFunction(std_String_fromCodePoint, null, codePoint);
831 SetIsInlinableLargeFunction(StringIteratorNext);
834 var collatorCache = new_Record();
837 * Compare this String against that String, using the locale and collation
840 * Spec: ECMAScript Internationalization API Specification, 13.1.1.
842 function String_localeCompare(that) {
844 if (IsNullOrUndefined(this)) {
845 ThrowIncompatibleMethod("localeCompare", this);
849 var S = ToString(this);
850 var That = ToString(that);
853 var locales = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
854 var options = ArgumentsLength() > 2 ? GetArgument(2) : undefined;
858 if (locales === undefined && options === undefined) {
859 // This cache only optimizes for the old ES5 localeCompare without
860 // locales and options.
861 if (!intl_IsRuntimeDefaultLocale(collatorCache.runtimeDefaultLocale)) {
862 collatorCache.collator = intl_Collator(locales, options);
863 collatorCache.runtimeDefaultLocale = intl_RuntimeDefaultLocale();
865 collator = collatorCache.collator;
867 collator = intl_Collator(locales, options);
871 return intl_CompareStrings(collator, S, That);
875 * 13.1.2 String.prototype.toLocaleLowerCase ( [ locales ] )
877 * ES2017 Intl draft rev 94045d234762ad107a3d09bb6f7381a65f1a2f9b
879 function String_toLocaleLowerCase() {
881 if (IsNullOrUndefined(this)) {
882 ThrowIncompatibleMethod("toLocaleLowerCase", this);
886 var string = ToString(this);
888 // Handle the common cases (no locales argument or a single string
890 var locales = ArgumentsLength() ? GetArgument(0) : undefined;
892 if (locales === undefined) {
894 requestedLocale = undefined;
895 } else if (typeof locales === "string") {
897 requestedLocale = intl_ValidateAndCanonicalizeLanguageTag(locales, false);
900 var requestedLocales = CanonicalizeLocaleList(locales);
903 requestedLocale = requestedLocales.length ? requestedLocales[0] : undefined;
906 // Trivial case: When the input is empty, directly return the empty string.
907 if (string.length === 0) {
911 if (requestedLocale === undefined) {
912 requestedLocale = DefaultLocale();
916 return intl_toLocaleLowerCase(string, requestedLocale);
920 * 13.1.3 String.prototype.toLocaleUpperCase ( [ locales ] )
922 * ES2017 Intl draft rev 94045d234762ad107a3d09bb6f7381a65f1a2f9b
924 function String_toLocaleUpperCase() {
926 if (IsNullOrUndefined(this)) {
927 ThrowIncompatibleMethod("toLocaleUpperCase", this);
931 var string = ToString(this);
933 // Handle the common cases (no locales argument or a single string
935 var locales = ArgumentsLength() ? GetArgument(0) : undefined;
937 if (locales === undefined) {
939 requestedLocale = undefined;
940 } else if (typeof locales === "string") {
942 requestedLocale = intl_ValidateAndCanonicalizeLanguageTag(locales, false);
945 var requestedLocales = CanonicalizeLocaleList(locales);
948 requestedLocale = requestedLocales.length ? requestedLocales[0] : undefined;
951 // Trivial case: When the input is empty, directly return the empty string.
952 if (string.length === 0) {
956 if (requestedLocale === undefined) {
957 requestedLocale = DefaultLocale();
961 return intl_toLocaleUpperCase(string, requestedLocale);
963 #endif // JS_HAS_INTL_API
965 // ES2018 draft rev 8fadde42cf6a9879b4ab0cb6142b31c4ee501667
966 // 21.1.2.4 String.raw ( template, ...substitutions )
967 function String_static_raw(callSite /*, ...substitutions*/) {
968 // Steps 1-2 (not applicable).
971 var cooked = ToObject(callSite);
974 var raw = ToObject(cooked.raw);
977 var literalSegments = ToLength(raw.length);
980 if (literalSegments === 0) {
984 // Special case for |String.raw `<literal>`| callers to avoid falling into
985 // the loop code below.
986 if (literalSegments === 1) {
987 return ToString(raw[0]);
990 // Steps 7-9 were reordered to use ArgumentsLength/GetArgument instead of a
991 // rest parameter, because the former is currently more optimized.
993 // String.raw intersperses the substitution elements between the literal
994 // segments, i.e. a substitution is added iff there are still pending
995 // literal segments. Furthermore by moving the access to |raw[0]| outside
996 // of the loop, we can use |nextIndex| to index into both, the |raw| array
997 // and the arguments.
999 // Steps 7 (implicit) and 9.a-c.
1000 var resultString = ToString(raw[0]);
1002 // Steps 8-9, 9.d, and 9.i.
1003 for (var nextIndex = 1; nextIndex < literalSegments; nextIndex++) {
1005 if (nextIndex < ArgumentsLength()) {
1006 resultString += ToString(GetArgument(nextIndex));
1010 resultString += ToString(raw[nextIndex]);
1014 return resultString;
1017 // ES6 draft 2014-04-27 B.2.3.3
1018 function String_big() {
1019 if (IsNullOrUndefined(this)) {
1020 ThrowIncompatibleMethod("big", this);
1022 return "<big>" + ToString(this) + "</big>";
1025 // ES6 draft 2014-04-27 B.2.3.4
1026 function String_blink() {
1027 if (IsNullOrUndefined(this)) {
1028 ThrowIncompatibleMethod("blink", this);
1030 return "<blink>" + ToString(this) + "</blink>";
1033 // ES6 draft 2014-04-27 B.2.3.5
1034 function String_bold() {
1035 if (IsNullOrUndefined(this)) {
1036 ThrowIncompatibleMethod("bold", this);
1038 return "<b>" + ToString(this) + "</b>";
1041 // ES6 draft 2014-04-27 B.2.3.6
1042 function String_fixed() {
1043 if (IsNullOrUndefined(this)) {
1044 ThrowIncompatibleMethod("fixed", this);
1046 return "<tt>" + ToString(this) + "</tt>";
1049 // ES6 draft 2014-04-27 B.2.3.9
1050 function String_italics() {
1051 if (IsNullOrUndefined(this)) {
1052 ThrowIncompatibleMethod("italics", this);
1054 return "<i>" + ToString(this) + "</i>";
1057 // ES6 draft 2014-04-27 B.2.3.11
1058 function String_small() {
1059 if (IsNullOrUndefined(this)) {
1060 ThrowIncompatibleMethod("small", this);
1062 return "<small>" + ToString(this) + "</small>";
1065 // ES6 draft 2014-04-27 B.2.3.12
1066 function String_strike() {
1067 if (IsNullOrUndefined(this)) {
1068 ThrowIncompatibleMethod("strike", this);
1070 return "<strike>" + ToString(this) + "</strike>";
1073 // ES6 draft 2014-04-27 B.2.3.13
1074 function String_sub() {
1075 if (IsNullOrUndefined(this)) {
1076 ThrowIncompatibleMethod("sub", this);
1078 return "<sub>" + ToString(this) + "</sub>";
1081 // ES6 draft 2014-04-27 B.2.3.14
1082 function String_sup() {
1083 if (IsNullOrUndefined(this)) {
1084 ThrowIncompatibleMethod("sup", this);
1086 return "<sup>" + ToString(this) + "</sup>";
1089 function EscapeAttributeValue(v) {
1090 var inputStr = ToString(v);
1091 return StringReplaceAllString(inputStr, '"', """);
1094 // ES6 draft 2014-04-27 B.2.3.2
1095 function String_anchor(name) {
1096 if (IsNullOrUndefined(this)) {
1097 ThrowIncompatibleMethod("anchor", this);
1099 var S = ToString(this);
1100 return '<a name="' + EscapeAttributeValue(name) + '">' + S + "</a>";
1103 // ES6 draft 2014-04-27 B.2.3.7
1104 function String_fontcolor(color) {
1105 if (IsNullOrUndefined(this)) {
1106 ThrowIncompatibleMethod("fontcolor", this);
1108 var S = ToString(this);
1109 return '<font color="' + EscapeAttributeValue(color) + '">' + S + "</font>";
1112 // ES6 draft 2014-04-27 B.2.3.8
1113 function String_fontsize(size) {
1114 if (IsNullOrUndefined(this)) {
1115 ThrowIncompatibleMethod("fontsize", this);
1117 var S = ToString(this);
1118 return '<font size="' + EscapeAttributeValue(size) + '">' + S + "</font>";
1121 // ES6 draft 2014-04-27 B.2.3.10
1122 function String_link(url) {
1123 if (IsNullOrUndefined(this)) {
1124 ThrowIncompatibleMethod("link", this);
1126 var S = ToString(this);
1127 return '<a href="' + EscapeAttributeValue(url) + '">' + S + "</a>";