JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); int len = s.size(); JSValue a0 = args.at(0); JSValue a1 = args.at(1); double start = a0.toNumber(exec); double end = a1.toNumber(exec); if (isnan(start)) start = 0; if (isnan(end)) end = 0; if (start < 0) start = 0; if (end < 0) end = 0; if (start > len) start = len; if (end > len) end = len; if (a1.isUndefined()) end = len; if (start > end) { double temp = end; end = start; start = temp; } return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(end) - static_cast<unsigned>(start)); }
JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); UString linkText = a0.toString(exec); unsigned linkTextSize = linkText.size(); unsigned stringSize = s.size(); unsigned bufferSize = 15 + linkTextSize + stringSize; UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); if (!buffer) return jsUndefined(); buffer[0] = '<'; buffer[1] = 'a'; buffer[2] = ' '; buffer[3] = 'h'; buffer[4] = 'r'; buffer[5] = 'e'; buffer[6] = 'f'; buffer[7] = '='; buffer[8] = '"'; memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar)); buffer[9 + linkTextSize] = '"'; buffer[10 + linkTextSize] = '>'; memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar)); buffer[11 + linkTextSize + stringSize] = '<'; buffer[12 + linkTextSize + stringSize] = '/'; buffer[13 + linkTextSize + stringSize] = 'a'; buffer[14 + linkTextSize + stringSize] = '>'; return jsNontrivialString(exec, UString(buffer, bufferSize, false)); }
JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { if (args.size() < 1) return jsNumber(exec, 0); UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); return jsNumber(exec, localeCompare(s, a0.toString(exec))); }
JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) s += (*it).toString(exec); return jsString(exec, s); }
JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); UString u = s; RefPtr<RegExp> reg; RegExpObject* imp = 0; if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* * ECMA 15.5.4.12 String.prototype.search (regexp) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength; regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); if (!(reg->global())) { // case without 'g' flag is handled like RegExp.prototype.exec if (pos < 0) return jsNull(); return regExpConstructor->arrayOfMatches(exec); } // return array of matches MarkedArgumentBuffer list; int lastIndex = 0; while (pos >= 0) { list.append(jsSubstring(exec, u, pos, matchLength)); lastIndex = pos; pos += matchLength == 0 ? 1 : matchLength; regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength); } if (imp) imp->setLastIndex(lastIndex); if (list.isEmpty()) { // if there are no matches at all, it's important to return // Null instead of an empty array, because this matches // other browsers and because Null is a false value. return jsNull(); } return constructArray(exec, list); }
JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); int len = s.size(); JSValue a0 = args.at(0); JSValue a1 = args.at(1); UString u2 = a0.toString(exec); double dpos = a1.toIntegerPreserveNaN(exec); if (dpos < 0) dpos = 0; else if (!(dpos <= len)) // true for NaN dpos = len; return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos))); }
JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); unsigned len = s.size(); JSValue a0 = args.at(0); if (a0.isUInt32Fast()) { uint32_t i = a0.getUInt32Fast(); if (i < len) return jsSingleCharacterSubstring(exec, s, i); return jsEmptyString(exec); } double dpos = a0.toInteger(exec); if (dpos >= 0 && dpos < len) return jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos)); return jsEmptyString(exec); }
JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); unsigned len = s.size(); JSValue a0 = args.at(0); if (a0.isUInt32Fast()) { uint32_t i = a0.getUInt32Fast(); if (i < len) return jsNumber(exec, s.data()[i]); return jsNaN(exec); } double dpos = a0.toInteger(exec); if (dpos >= 0 && dpos < len) return jsNumber(exec, s[static_cast<int>(dpos)]); return jsNaN(exec); }
JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); int len = s.size(); JSValue a0 = args.at(0); JSValue a1 = args.at(1); double start = a0.toInteger(exec); double length = a1.isUndefined() ? len : a1.toInteger(exec); if (start >= len || length <= 0) return jsEmptyString(exec); if (start < 0) { start += len; if (start < 0) start = 0; } if (start + length > len) length = len - start; return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(length)); }
JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); uint32_t smallInteger; if (a0.getUInt32(smallInteger) && smallInteger <= 9) { unsigned stringSize = s.size(); unsigned bufferSize = 22 + stringSize; UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); if (!buffer) return jsUndefined(); buffer[0] = '<'; buffer[1] = 'f'; buffer[2] = 'o'; buffer[3] = 'n'; buffer[4] = 't'; buffer[5] = ' '; buffer[6] = 's'; buffer[7] = 'i'; buffer[8] = 'z'; buffer[9] = 'e'; buffer[10] = '='; buffer[11] = '"'; buffer[12] = '0' + smallInteger; buffer[13] = '"'; buffer[14] = '>'; memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar)); buffer[15 + stringSize] = '<'; buffer[16 + stringSize] = '/'; buffer[17 + stringSize] = 'f'; buffer[18 + stringSize] = 'o'; buffer[19 + stringSize] = 'n'; buffer[20 + stringSize] = 't'; buffer[21 + stringSize] = '>'; return jsNontrivialString(exec, UString(buffer, bufferSize, false)); } return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>"); }
JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); int len = s.size(); JSValue a0 = args.at(0); JSValue a1 = args.at(1); // The arg processing is very much like ArrayProtoFunc::Slice double start = a0.toInteger(exec); double end = a1.isUndefined() ? len : a1.toInteger(exec); double from = start < 0 ? len + start : start; double to = end < 0 ? len + end : end; if (to > from && to > 0 && from < len) { if (from < 0) from = 0; if (to > len) to = len; return jsSubstring(exec, s, static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from)); } return jsEmptyString(exec); }
JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); int len = s.size(); JSValue a0 = args.at(0); JSValue a1 = args.at(1); UString u2 = a0.toString(exec); int pos; if (a1.isUndefined()) pos = 0; else if (a1.isUInt32Fast()) pos = min<uint32_t>(a1.getUInt32Fast(), len); else { double dpos = a1.toInteger(exec); if (dpos < 0) dpos = 0; else if (dpos > len) dpos = len; pos = static_cast<int>(dpos); } return jsNumber(exec, s.find(u2, pos)); }
JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); UString u = s; RefPtr<RegExp> reg; if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* * ECMA 15.5.4.12 String.prototype.search (regexp) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength; regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); return jsNumber(exec, pos); }
JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); JSValue a1 = args.at(1); JSArray* result = constructEmptyArray(exec); unsigned i = 0; int p0 = 0; unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec); if (a0.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(a0)->regExp(); if (s.isEmpty() && reg->match(s, 0) >= 0) { // empty string matched by regexp -> empty array return result; } int pos = 0; while (i != limit && pos < s.size()) { OwnArrayPtr<int> ovector; int mpos = reg->match(s, pos, &ovector); if (mpos < 0) break; int mlen = ovector[1] - ovector[0]; pos = mpos + (mlen == 0 ? 1 : mlen); if (mpos != p0 || mlen) { result->put(exec, i++, jsSubstring(exec, s, p0, mpos - p0)); p0 = mpos + mlen; } for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) { int spos = ovector[si * 2]; if (spos < 0) result->put(exec, i++, jsUndefined()); else result->put(exec, i++, jsSubstring(exec, s, spos, ovector[si * 2 + 1] - spos)); } } } else { UString u2 = a0.toString(exec); if (u2.isEmpty()) { if (s.isEmpty()) { // empty separator matches empty string -> empty array return result; } while (i != limit && p0 < s.size() - 1) result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++)); } else { int pos; while (i != limit && (pos = s.find(u2, p0)) >= 0) { result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0)); p0 = pos + u2.size(); } } } // add remaining string if (i != limit) result->put(exec, i++, jsSubstring(exec, s, p0, s.size() - p0)); return result; }
JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>"); }
JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); return jsNontrivialString(exec, "<sup>" + s + "</sup>"); }
JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); return jsString(exec, "<tt>" + s + "</tt>"); }