| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include 'src/builtins/builtins-string-gen.h' |
| |
| namespace string { |
| // ES6 #sec-string.prototype.tostring |
| transitioning javascript builtin |
| StringPrototypeToString(js-implicit context: Context)(receiver: Object): |
| Object { |
| return ToThisValue(receiver, kString, 'String.prototype.toString'); |
| } |
| |
| // ES6 #sec-string.prototype.valueof |
| transitioning javascript builtin |
| StringPrototypeValueOf(js-implicit context: Context)(receiver: Object): |
| Object { |
| return ToThisValue(receiver, kString, 'String.prototype.valueOf'); |
| } |
| |
| extern macro StringBuiltinsAssembler::LoadSurrogatePairAt( |
| String, intptr, intptr, constexpr UnicodeEncoding): int32; |
| extern macro StringFromSingleUTF16EncodedCodePoint(int32): String; |
| |
| // This function assumes StringPrimitiveWithNoCustomIteration is true. |
| transitioning builtin StringToList(implicit context: Context)(string: String): |
| JSArray { |
| const kind = PACKED_ELEMENTS; |
| const stringLength: intptr = string.length_intptr; |
| |
| const map: Map = LoadJSArrayElementsMap(kind, LoadNativeContext(context)); |
| const array: JSArray = AllocateJSArray( |
| kind, map, stringLength, SmiTag(stringLength), |
| kAllowLargeObjectAllocation); |
| const elements = UnsafeCast<FixedArray>(array.elements); |
| const encoding = UTF16; |
| let arrayLength: Smi = 0; |
| let i: intptr = 0; |
| while (i < stringLength) { |
| const ch: int32 = LoadSurrogatePairAt(string, stringLength, i, encoding); |
| const value: String = StringFromSingleUTF16EncodedCodePoint(ch); |
| elements[arrayLength] = value; |
| // Increment and continue the loop. |
| i = i + value.length_intptr; |
| arrayLength++; |
| } |
| assert(arrayLength >= 0); |
| assert(SmiTag(stringLength) >= arrayLength); |
| array.length = arrayLength; |
| |
| return array; |
| } |
| |
| transitioning macro GenerateStringAt(implicit context: Context)( |
| receiver: Object, position: Object, |
| methodName: constexpr string): never labels |
| IfInBounds(String, intptr, intptr), IfOutOfBounds { |
| // Check that {receiver} is coercible to Object and convert it to a String. |
| const string: String = ToThisString(receiver, methodName); |
| // Convert the {position} to a Smi and check that it's in bounds of |
| // the {string}. |
| const indexNumber: Number = |
| ToInteger_Inline(context, position, kTruncateMinusZero); |
| if (TaggedIsNotSmi(indexNumber)) goto IfOutOfBounds; |
| const index: intptr = SmiUntag(UnsafeCast<Smi>(indexNumber)); |
| const length: intptr = string.length_intptr; |
| if (Convert<uintptr>(index) >= Convert<uintptr>(length)) goto IfOutOfBounds; |
| goto IfInBounds(string, index, length); |
| } |
| |
| // ES6 #sec-string.prototype.charat |
| transitioning javascript builtin StringPrototypeCharAt( |
| js-implicit context: Context, |
| receiver: Object)(position: Object): Object { |
| try { |
| GenerateStringAt(receiver, position, 'String.prototype.charAt') |
| otherwise IfInBounds, IfOutOfBounds; |
| } |
| label IfInBounds(string: String, index: intptr, _length: intptr) { |
| const code: int32 = StringCharCodeAt(string, index); |
| return StringFromSingleCharCode(code); |
| } |
| label IfOutOfBounds { |
| return kEmptyString; |
| } |
| } |
| |
| // ES6 #sec-string.prototype.charcodeat |
| transitioning javascript builtin StringPrototypeCharCodeAt( |
| js-implicit context: Context, |
| receiver: Object)(position: Object): Object { |
| try { |
| GenerateStringAt(receiver, position, 'String.prototype.charCodeAt') |
| otherwise IfInBounds, IfOutOfBounds; |
| } |
| label IfInBounds(string: String, index: intptr, _length: intptr) { |
| const code: int32 = StringCharCodeAt(string, index); |
| return Convert<Smi>(code); |
| } |
| label IfOutOfBounds { |
| return kNaN; |
| } |
| } |
| |
| // ES6 #sec-string.prototype.codepointat |
| transitioning javascript builtin StringPrototypeCodePointAt( |
| js-implicit context: Context, |
| receiver: Object)(position: Object): Object { |
| try { |
| GenerateStringAt(receiver, position, 'String.prototype.codePointAt') |
| otherwise IfInBounds, IfOutOfBounds; |
| } |
| label IfInBounds(string: String, index: intptr, length: intptr) { |
| // This is always a call to a builtin from Javascript, so we need to |
| // produce UTF32. |
| const code: int32 = LoadSurrogatePairAt(string, length, index, UTF32); |
| return Convert<Smi>(code); |
| } |
| label IfOutOfBounds { |
| return Undefined; |
| } |
| } |
| |
| // ES6 String.prototype.concat(...args) |
| // ES6 #sec-string.prototype.concat |
| transitioning javascript builtin StringPrototypeConcat( |
| js-implicit context: Context, receiver: Object)(...arguments): Object { |
| // Check that {receiver} is coercible to Object and convert it to a String. |
| let string: String = ToThisString(receiver, 'String.prototype.concat'); |
| |
| // Concatenate all the arguments passed to this builtin. |
| const length: intptr = Convert<intptr>(arguments.length); |
| for (let i: intptr = 0; i < length; i++) { |
| const temp: String = ToString_Inline(context, arguments[i]); |
| string = string + temp; |
| } |
| return string; |
| } |
| } |