| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index 30ec45199aa0a8bcc6465b251ceeff746003672a..1c78f00cde744587048c49b57493e95e14d8e559 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -4298,6 +4298,69 @@ BUILTIN(ObjectProtoToString) {
|
| // -----------------------------------------------------------------------------
|
| // ES6 section 21.1 String Objects
|
|
|
| +namespace {
|
| +
|
| +bool ToUint16(Handle<Object> value, uint16_t* result) {
|
| + if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) {
|
| + *result = DoubleToUint32(value->Number());
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// ES6 21.1.2.1 String.fromCharCode ( ...codeUnits )
|
| +BUILTIN(StringFromCharCode) {
|
| + HandleScope scope(isolate);
|
| + // Check resulting string length.
|
| + int index = 0;
|
| + Handle<String> result;
|
| + int const length = args.length() - 1;
|
| + if (length == 0) return isolate->heap()->empty_string();
|
| + DCHECK_LT(0, length);
|
| + // Load the first character code.
|
| + uint16_t code;
|
| + if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception();
|
| + // Assume that the resulting String contains only one byte characters.
|
| + if (code <= String::kMaxOneByteCharCodeU) {
|
| + // Check for single one-byte character fast case.
|
| + if (length == 1) {
|
| + return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
|
| + }
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, result, isolate->factory()->NewRawOneByteString(length));
|
| + do {
|
| + Handle<SeqOneByteString>::cast(result)->Set(index, code);
|
| + if (++index == length) break;
|
| + if (!ToUint16(args.at<Object>(1 + index), &code)) {
|
| + return isolate->heap()->exception();
|
| + }
|
| + } while (code <= String::kMaxOneByteCharCodeU);
|
| + }
|
| + // Check if all characters fit into the one byte range.
|
| + if (index < length) {
|
| + // Fallback to two byte string.
|
| + Handle<String> new_result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, new_result, isolate->factory()->NewRawTwoByteString(length));
|
| + for (int new_index = 0; new_index < index; ++new_index) {
|
| + uint16_t new_code =
|
| + Handle<SeqOneByteString>::cast(result)->Get(new_index);
|
| + Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code);
|
| + }
|
| + while (true) {
|
| + Handle<SeqTwoByteString>::cast(new_result)->Set(index, code);
|
| + if (++index == length) break;
|
| + if (!ToUint16(args.at<Object>(1 + index), &code)) {
|
| + return isolate->heap()->exception();
|
| + }
|
| + }
|
| + result = new_result;
|
| + }
|
| + return *result;
|
| +}
|
| +
|
| // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
|
| void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
|
| typedef CodeStubAssembler::Label Label;
|
|
|