Files
tubestation/js/src/builtin/String.js

134 lines
4.0 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*global intl_Collator: false, */
var collatorCache = new Record();
/* ES6 20121122 draft 15.5.4.21. */
function String_repeat(count) {
// Steps 1-3.
CheckObjectCoercible(this);
var S = ToString(this);
// Steps 4-5.
var n = ToInteger(count);
// Steps 6-7.
if (n < 0)
ThrowError(JSMSG_NEGATIVE_REPETITION_COUNT); // a RangeError
if (!(n * S.length < (1 << 28)))
ThrowError(JSMSG_RESULTING_STRING_TOO_LARGE); // a RangeError
// Communicate |n|'s possible range to the compiler.
n = n & ((1 << 28) - 1);
// Steps 8-9.
var T = "";
for (;;) {
if (n & 1)
T += S;
n >>= 1;
if (n)
S += S;
else
break;
}
return T;
}
#define STRING_ITERATOR_SLOT_ITERATED_OBJECT 0
#define STRING_ITERATOR_SLOT_NEXT_INDEX 1
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
function String_iterator() {
CheckObjectCoercible(this);
var S = ToString(this);
var iterator = NewStringIterator();
UnsafeSetReservedSlot(iterator, STRING_ITERATOR_SLOT_ITERATED_OBJECT, S);
UnsafeSetReservedSlot(iterator, STRING_ITERATOR_SLOT_NEXT_INDEX, 0);
return iterator;
}
function StringIteratorIdentity() {
return this;
}
function StringIteratorNext() {
// FIXME: Cross-compartment wrapper StringIterator objects should pass this test. Bug 924059.
if (!IsObject(this) || !IsStringIterator(this))
ThrowError(JSMSG_INCOMPATIBLE_METHOD, "StringIterator", "next", ToString(this));
var S = UnsafeGetReservedSlot(this, STRING_ITERATOR_SLOT_ITERATED_OBJECT);
var index = UnsafeGetReservedSlot(this, STRING_ITERATOR_SLOT_NEXT_INDEX);
var size = S.length;
if (index >= size) {
return { value: undefined, done: true };
}
var charCount = 1;
var first = callFunction(std_String_charCodeAt, S, index);
if (first >= 0xD800 && first <= 0xDBFF && index + 1 < size) {
var second = callFunction(std_String_charCodeAt, S, index + 1);
if (second >= 0xDC00 && second <= 0xDFFF) {
charCount = 2;
}
}
UnsafeSetReservedSlot(this, STRING_ITERATOR_SLOT_NEXT_INDEX, index + charCount);
var value = callFunction(std_String_substring, S, index, index + charCount);
return { value: value, done: false };
}
/**
* Compare this String against that String, using the locale and collation
* options provided.
*
* Spec: ECMAScript Internationalization API Specification, 13.1.1.
*/
function String_localeCompare(that) {
// Steps 1-3.
CheckObjectCoercible(this);
var S = ToString(this);
var That = ToString(that);
// Steps 4-5.
var locales = arguments.length > 1 ? arguments[1] : undefined;
var options = arguments.length > 2 ? arguments[2] : undefined;
// Step 6.
var collator;
if (locales === undefined && options === undefined) {
// This cache only optimizes for the old ES5 localeCompare without
// locales and options.
if (collatorCache.collator === undefined)
collatorCache.collator = intl_Collator(locales, options);
collator = collatorCache.collator;
} else {
collator = intl_Collator(locales, options);
}
// Step 7.
return intl_CompareStrings(collator, S, That);
}
/**
* Compare String str1 against String str2, using the locale and collation
* options provided.
*
* Mozilla proprietary.
* Spec: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String#String_generic_methods
*/
function String_static_localeCompare(str1, str2) {
if (arguments.length < 1)
ThrowError(JSMSG_MISSING_FUN_ARG, 0, "String.localeCompare");
var locales = arguments.length > 2 ? arguments[2] : undefined;
var options = arguments.length > 3 ? arguments[3] : undefined;
return callFunction(String_localeCompare, str1, str2, locales, options);
}