# HG changeset patch # Parent 52c773840b0083db00c24c171b9d6f1824f2f82a # User Benjamin Peterson Bug 799499 - implement String.toArray diff --git a/js/src/jit-test/tests/basic/string-toArray.js b/js/src/jit-test/tests/basic/string-toArray.js new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/basic/string-toArray.js @@ -0,0 +1,7 @@ +load(libdir + "eqArrayHelper.js"); + +assertEqArray("".toArray(), []); +assertEqArray("a".toArray(), ["a"]); +assertEqArray("abcdef".toArray(), ["a", "b", "c", "d", "e", "f"]); +var myobj = {toString : (function () "abc"), toArray : String.prototype.toArray}; +assertEqArray(myobj.toArray(myobj), ["a", "b", "c"]); diff --git a/js/src/js.msg b/js/src/js.msg --- a/js/src/js.msg +++ b/js/src/js.msg @@ -191,17 +191,17 @@ MSG_DEF(JSMSG_OUT_OF_MEMORY, 13 MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal") MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression") MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment") MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal") MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 142, 0, JSEXN_TYPEERR, "bad cloned function scope chain") MSG_DEF(JSMSG_SHARPVAR_TOO_BIG, 143, 0, JSEXN_SYNTAXERR, "overlarge sharp variable number") MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character") MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant") -MSG_DEF(JSMSG_UNUSED146, 146, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_STRING_TOO_LONG_FOR_ARRAY, 146, 0, JSEXN_RANGEERR, "string too long to fit in array") MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_INTERNALERR, "uncaught exception: {0}") MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference") MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses") MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range") MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_TYPEERR, "invalid {0} usage") MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length") MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}") MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array") diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -557,16 +557,57 @@ ValueToIntegerRange(JSContext *cx, const *out = INT32_MIN; else *out = int32_t(d); } return true; } +/* ES6 20121009 draft 15.5.4.25. */ +static JSBool +str_toArray(JSContext *cx, unsigned argc, Value *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + // Steps 1-2 + Rooted str(cx, ThisToStringForStringProto(cx, args)); + if (!str) + return false; + + if (str->length() > UINT32_MAX) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_STRING_TOO_LONG_FOR_ARRAY); + return false; + } + + // Step 3 + RootedObject result(cx, NewDenseAllocatedArray(cx, str->length(), NULL)); + if (!result) + return false; + result->setDenseArrayInitializedLength(str->length()); + js::types::AddTypePropertyId(cx, result, JSID_VOID, Type::StringType()); + + // Steps 4, 5, 6 + Rooted c(cx); + for (size_t n = 0; n < str->length(); n++) { + // Step 6a + c = cx->runtime->staticStrings.getUnitStringForElement(cx, str, n); + if (!c) + return false; + + // Step 6b + result->initDenseArrayElement(n, StringValue(c)); + } + + // Step 7 + args.rval().setObject(*result.get()); + + return true; +} + static JSBool str_substring(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedString str(cx, ThisToStringForStringProto(cx, args)); if (!str) return false; @@ -3119,16 +3160,17 @@ static JSFunctionSpec string_methods[] = JS_FN("localeCompare", str_localeCompare, 1,JSFUN_GENERIC_NATIVE), /* Perl-ish methods (search is actually Python-esque). */ JS_FN("match", str_match, 1,JSFUN_GENERIC_NATIVE), JS_FN("search", str_search, 1,JSFUN_GENERIC_NATIVE), JS_FN("replace", str_replace, 2,JSFUN_GENERIC_NATIVE), JS_FN("split", str_split, 2,JSFUN_GENERIC_NATIVE), JS_FN("substr", str_substr, 2,JSFUN_GENERIC_NATIVE), + JS_FN("toArray", str_toArray, 1,JSFUN_GENERIC_NATIVE), /* Python-esque sequence methods. */ JS_FN("concat", str_concat, 1,JSFUN_GENERIC_NATIVE), JS_FN("slice", str_slice, 2,JSFUN_GENERIC_NATIVE), /* HTML string methods. */ #if JS_HAS_STR_HTML_HELPERS JS_FN("bold", str_bold, 0,0),