From 4749b33d3facd1b5e2c5ed64f9ccabcce1eb0f8c Mon Sep 17 00:00:00 2001 From: yp9522 Date: Mon, 14 Jul 2025 09:41:47 +0800 Subject: [PATCH] modify string get return value Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICLZHK Signed-off-by: yp9522 --- .../optimizer/ir_builder/inst_builder-inl.h | 20 ++++ .../optimizer/ir_builder/inst_builder.h | 2 + .../intrinsics_ir_build_virtual_call_ets.inl | 5 +- .../ets/runtime/ets_libbase_runtime.yaml | 2 +- .../runtime/intrinsics/std_core_String.cpp | 14 ++- .../plugins/ets/sdk/api/@ohos.buffer.ets | 4 +- static_core/plugins/ets/sdk/api/@ohos.uri.ets | 12 +- static_core/plugins/ets/sdk/api/@ohos.url.ets | 113 ++++++++++-------- .../plugins/ets/sdk/api/@ohos.util.ets | 2 +- static_core/plugins/ets/sdk/api/@ohos.xml.ets | 6 +- .../plugins/ets/stdlib/std/core/String.ets | 6 +- .../ets/tests/checked/ets_string_get.ets | 14 +-- .../ets_func_tests/std/core/StringGetTest.ets | 105 ++++++++++++++++ .../api/@ohos/util/GenerateRandomUUIDTest.ets | 10 +- .../api/@ohos/util/TextEncoderTest.ets | 7 +- .../ets_test_suite/strings/string_api.ets | 8 +- 16 files changed, 239 insertions(+), 91 deletions(-) create mode 100644 static_core/plugins/ets/tests/ets_func_tests/std/core/StringGetTest.ets diff --git a/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h b/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h index 4b6098f32b..879b2cdf66 100644 --- a/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h +++ b/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h @@ -1635,6 +1635,26 @@ bool InstBuilder::TryBuildStringCharAtIntrinsic(const BytecodeInstruction *bcIns return true; } +void InstBuilder::BuildStringGetIntrinsic(const BytecodeInstruction *bcInst, bool accRead, + RuntimeInterface::IntrinsicId intrinsicId) +{ + auto bcAddr = GetPc(bcInst->GetAddress()); + auto saveState = CreateSaveState(Opcode::SaveState, bcAddr); + + auto stringGet = graph_->CreateInstIntrinsic(DataType::REFERENCE, bcAddr, intrinsicId); + stringGet->AllocateInputTypes(GetGraph()->GetAllocator(), 3); // 3: number of inputs + + stringGet->AppendInput(GetArgDefinition(bcInst, 0, accRead)); + stringGet->AddInputType(DataType::REFERENCE); + stringGet->AppendInput(GetArgDefinition(bcInst, 1, accRead)); + stringGet->AddInputType(DataType::INT32); + stringGet->AppendInput(saveState); + stringGet->AddInputType(DataType::NO_TYPE); + + AddInstruction(saveState, stringGet); + UpdateDefinitionAcc(stringGet); +} + // NOLINTNEXTLINE(misc-definitions-in-headers) template void InstBuilder::BuildLoadFromAnyByName([[maybe_unused]] const BytecodeInstruction *bcInst, diff --git a/static_core/compiler/optimizer/ir_builder/inst_builder.h b/static_core/compiler/optimizer/ir_builder/inst_builder.h index 86f044787e..1e86a17238 100644 --- a/static_core/compiler/optimizer/ir_builder/inst_builder.h +++ b/static_core/compiler/optimizer/ir_builder/inst_builder.h @@ -379,6 +379,8 @@ private: anyCheck->SetIsTypeWasProfiled(typeWasProfiled); } + void BuildStringGetIntrinsic(const BytecodeInstruction *bcInst, bool accRead, + RuntimeInterface::IntrinsicId intrinsicId); bool TryBuildStringCharAtIntrinsic(const BytecodeInstruction *bcInst, bool accRead); template diff --git a/static_core/plugins/ets/compiler/intrinsics_ir_build_virtual_call_ets.inl b/static_core/plugins/ets/compiler/intrinsics_ir_build_virtual_call_ets.inl index b7b7c41fcb..d305c7e2ba 100644 --- a/static_core/plugins/ets/compiler/intrinsics_ir_build_virtual_call_ets.inl +++ b/static_core/plugins/ets/compiler/intrinsics_ir_build_virtual_call_ets.inl @@ -13,7 +13,10 @@ * limitations under the License. */ -case RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_STRING_GET: +case RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_STRING_GET: { + Builder()->BuildStringGetIntrinsic(bcInst_, ACC_READ, intrinsicId); + break; +} case RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_STRING_CHAR_AT: { if (!Builder()->TryBuildStringCharAtIntrinsic(bcInst_, ACC_READ)) { BuildDefaultVirtualCallIntrinsic(intrinsicId); diff --git a/static_core/plugins/ets/runtime/ets_libbase_runtime.yaml b/static_core/plugins/ets/runtime/ets_libbase_runtime.yaml index 8f6bfc0354..557f39a5f3 100644 --- a/static_core/plugins/ets/runtime/ets_libbase_runtime.yaml +++ b/static_core/plugins/ets/runtime/ets_libbase_runtime.yaml @@ -1127,7 +1127,7 @@ intrinsics: method_name: $_get static: false signature: - ret: u16 + ret: std.core.String args: [ i32 ] impl: ark::ets::intrinsics::StdCoreStringGet ########################## diff --git a/static_core/plugins/ets/runtime/intrinsics/std_core_String.cpp b/static_core/plugins/ets/runtime/intrinsics/std_core_String.cpp index 4b45bfaa5a..033f81302e 100644 --- a/static_core/plugins/ets/runtime/intrinsics/std_core_String.cpp +++ b/static_core/plugins/ets/runtime/intrinsics/std_core_String.cpp @@ -632,9 +632,17 @@ EtsString *StdCoreStringRepeat(EtsString *str, EtsInt count) return result; } -uint16_t StdCoreStringGet(EtsString *str, EtsInt index) +EtsString *StdCoreStringGet(EtsString *str, EtsInt index) { - return StdCoreStringCharAt(str, index); + auto strData = static_cast(StdCoreStringCharAt(str, index)); + auto *coro = EtsCoroutine::GetCurrent(); + if (coro->HasPendingException()) { + return nullptr; + } + if (strData < EtsPlatformTypes::ASCII_CHAR_TABLE_SIZE && coretypes::String::IsASCIICharacter(strData)) { + auto *cache = PlatformTypes()->GetAsciiCacheTable(); + return static_cast(cache->Get(strData)); + } + return EtsString::CreateFromUtf16(&strData, 1); } - } // namespace ark::ets::intrinsics diff --git a/static_core/plugins/ets/sdk/api/@ohos.buffer.ets b/static_core/plugins/ets/sdk/api/@ohos.buffer.ets index d4dff47def..9b901310c8 100644 --- a/static_core/plugins/ets/sdk/api/@ohos.buffer.ets +++ b/static_core/plugins/ets/sdk/api/@ohos.buffer.ets @@ -478,8 +478,8 @@ It must be >= 0 and <= uint32 max. Received value is: ${length}`) const sourceStr = ArrayBuffer.stringify(resolvedSource, fromEnc, 0, sourceBytesLength); let asciiSource = new StringBuilder("") for (let i = 0; i < sourceStr.length; ++i) { - if (sourceStr[i].toInt() <= 128) { - asciiSource.append(sourceStr[i]) + if (sourceStr.charAt(i).toInt() <= 128) { + asciiSource.append(sourceStr.charAt(i)) } else { asciiSource.append('?') } diff --git a/static_core/plugins/ets/sdk/api/@ohos.uri.ets b/static_core/plugins/ets/sdk/api/@ohos.uri.ets index 5fcad92b15..81bfbe4a6e 100644 --- a/static_core/plugins/ets/sdk/api/@ohos.uri.ets +++ b/static_core/plugins/ets/sdk/api/@ohos.uri.ets @@ -646,7 +646,7 @@ export namespace uri { this.data = this.data.substring(2); // 2:Intercept the string from the second subscript this.analysisHostAndPath(); this.checkErrAndThrow(); - } else if (this.data.length != 0 && this.data[0] == c'/') { + } else if (this.data.length != 0 && this.data.charAt(0) == c'/') { this.path = this.data; this.assignSchemeSpecificPart(); this.data = ""; @@ -738,8 +738,8 @@ export namespace uri { private analysisHost(isLawfulPort: boolean) { // find ipv4 or ipv6 or host - if (this.data.length > 0 && this.data[0] == c'[') { - if (this.data[this.data.length - 1] == c']') { + if (this.data.length > 0 && this.data.charAt(0) == c'[') { + if (this.data.charAt(this.data.length.toInt() - 1) == c']') { // IPV6 if (!isLawfulPort) { this.errStr = "Port does not conform to the rule."; @@ -905,7 +905,7 @@ export namespace uri { if (this.inputUri.length == index + 1) { return false; } - return this.inputUri[index + 1] == c'/'; + return this.inputUri.charAt(index.toInt() + 1) == c'/'; } addQueryValue(key: string, value: string) { @@ -928,7 +928,7 @@ export namespace uri { result += this.path; } if (str == "segment") { - let lastChar = result[result.length - 1]; + let lastChar = result.charAt(result.length.toInt() - 1); if (lastChar == c'/') { result += param; } else { @@ -1165,7 +1165,7 @@ export namespace uri { this.assignSchemeSpecificPart(); this.data = this.data.substring(2); // Skip the '//' this.analysisHostAndPath(); - } else if (this.data[0] === c'/') { + } else if (this.data.charAt(0) === c'/') { this.path = this.data; this.assignSchemeSpecificPart(); this.data = ""; diff --git a/static_core/plugins/ets/sdk/api/@ohos.url.ets b/static_core/plugins/ets/sdk/api/@ohos.url.ets index a125648afe..9954224b92 100644 --- a/static_core/plugins/ets/sdk/api/@ohos.url.ets +++ b/static_core/plugins/ets/sdk/api/@ohos.url.ets @@ -62,7 +62,7 @@ export namespace url { Helper.specialCharForBit[i] = 1; } for (let i = 0; i < specialSymbolsTmp.length; i++) { - let specialChar = specialSymbolsTmp[i][0]; + let specialChar = specialSymbolsTmp[i].charCodeAt(0); Helper.specialCharForBit[specialChar] = 1; } Helper.specialCharForBit[Helper.ASCII_127] = 1; @@ -219,7 +219,7 @@ export namespace url { } function isFileNotHost(input: string) { - return Char.isLetter(input[0]) && (input[1] == c':' || input[1] == c'|'); + return Char.isLetter(input.charAt(0)) && (input.charAt(1) == c':' || input.charAt(1) == c'|'); } function DecodeSpecialChars(input: string): string { @@ -230,7 +230,7 @@ export namespace url { } let pos: number = temp.indexOf("%"); while ((pos != -1) && (pos < len - 2)) { - if (Char.isHexDigit(temp[pos + 1]) && Char.isHexDigit(temp[pos + 2])) { + if (Char.isHexDigit(temp.charAt(pos.toInt() + 1)) && Char.isHexDigit(temp.charAt(pos.toInt() + 2))) { let subStr = temp.substring(pos + 1, pos + 3); let octNum: number = parseInt(subStr, 16); if (isNaN(octNum)) { @@ -342,7 +342,7 @@ export namespace url { function isRadix(input: string, radix: string): boolean { let len = input.length; for (let i = 0; i < len; i++) { - if (radix.indexOf(input[i]) == -1) { + if (radix.indexOf(input.charAt(i)) == -1) { return false; } } @@ -351,14 +351,14 @@ export namespace url { function isNumber(num: string, convension: number[]): boolean { let len: number = num.length; - if (len >= 2 && num[0] == c'0' && (num[1] == c'x' || num[1] == c'X')) { + if (len >= 2 && num.charAt(0) == c'0' && (num.charAt(1) == c'x' || num.charAt(1) == c'X')) { convension[0] = 16; let subStr = num.substring(2); if (subStr.length == 0) { return true; } return isRadix(subStr, "0123456789abcdefABCDEF"); - } else if (len >= 1 && num[0] == c'0') { + } else if (len >= 1 && num.charAt(0) == c'0') { convension[0] = 8; let subStr = num.substring(1); if (subStr.length == 0) { @@ -463,13 +463,13 @@ export namespace url { private ipv4Array: Array = new Array(); analysizeScheme(input: string): boolean { - if (!Char.isLetter(input[0])) { + if (!Char.isLetter(input.charAt(0))) { this.flags[INDEX_INVALID] = true; return false; } let sizeLen: number = input.length; for (let i = 1; i < sizeLen - 1; i++) { - if (!isAlphaNum(input[i]) && input[i] != c'+' && input[i] != c'-' && input[i] != c'.') { + if (!isAlphaNum(input.charAt(i)) && input.charAt(i) != c'+' && input.charAt(i) != c'-' && input.charAt(i) != c'.') { this.flags[INDEX_INVALID] = true; return false; } @@ -524,7 +524,7 @@ export namespace url { } let it = this.cPath[0]; - if (Char.isLetter(it[0]) && (it[1] == c':' || it[1] == c'|')) { + if (Char.isLetter(it.charAt(0)) && (it.charAt(1) == c':' || it.charAt(1) == c'|')) { if (it.length == 2) { this.cPath[0] = it[0] + ':'; this.flags[INDEX_HOST] = false; @@ -682,7 +682,7 @@ export namespace url { private analysizeOpaqueHost(input: string) { let inputSize: number = input.length; for (let i = 0; i < inputSize; i++) { - let ch = new Char(input[i]); + let ch = new Char(input.charAt(i)); let result = Helper.specialcharacter.indexOf(ch.toString()); if ((ch != c'%') && (result != -1)) { this.flags[INDEX_INVALID] = true; @@ -699,8 +699,8 @@ export namespace url { return; } let inputLength = input.length; - if (input[0] == c'[') { - if (input[inputLength - 1] == c']') { + if (input.charAt(0) == c'[') { + if (input.charAt(inputLength.toInt() - 1) == c']') { input = input.substring(1, inputLength - 1); this.analysizeIPv6Host(input); return; @@ -722,7 +722,9 @@ export namespace url { private analysizeFile(input: string) { let special: boolean = true; - if ((input[0] == c'/' || input[0] == c'\\') && (input[1] == c'/' || input[1] == c'\\')) { + if ((input.charAt(0) == c'/' || input.charAt(0) == c'\\') && + (input.charAt(1) == c'/' || input.charAt(1) == c'\\')) + { let temp: string = input.substring(2); let pos: number = 0; if (((pos = temp.indexOf('/')) != -1 || (pos = temp.indexOf('\\')) != -1) && pos == 0) { @@ -739,7 +741,7 @@ export namespace url { } } } else { - if (input[0] == c'/' || input[0] == c'\\') { + if (input.charAt(0) == c'/' || input.charAt(0) == c'\\') { input = input.substring(1); } this.analysizeFilePath(input); @@ -749,7 +751,7 @@ export namespace url { private analysizeUsernameAndPasswd(strHost: string): string { let pos: number = strHost.length - 1; for (; pos >= 0; pos--) { - if (strHost[pos] == c'@') { + if (strHost.charAt(pos.toInt()) == c'@') { break; } } @@ -792,7 +794,7 @@ export namespace url { return; } for (let i = 0; i < port.length; i++) { - if (!Char.isDecDigit(port[i])) { + if (!Char.isDecDigit(port.charAt(i))) { this.flags[INDEX_INVALID] = true; return; } @@ -863,7 +865,7 @@ export namespace url { let special: boolean = true; let inputLen: number = input.length; for (pos = 0; pos < inputLen; pos++) { - if (input[pos] == c'/' || input[pos] == c'\\') { + if (input.charAt(pos.toInt()) == c'/' || input.charAt(pos.toInt()) == c'\\') { break; } } @@ -876,7 +878,7 @@ export namespace url { this.flags[INDEX_INVALID] = true; return; } - if (strHost[strHost.length - 1] != c']' && (strHost.lastIndexOf(':') != -1)) { + if (strHost.charAt(strHost.length.toInt() - 1) != c']' && (strHost.lastIndexOf(':') != -1)) { pos = strHost.lastIndexOf(':'); if (pos != -1) { let port: string = strHost.substring(pos + 1); @@ -884,7 +886,9 @@ export namespace url { this.analysizePort(port); } } - if (strHost[strHost.length - 1] != c']' && strHost.lastIndexOf(':') != -1 && this.flags[INDEX_INVALID]) { + if (strHost.charAt(strHost.length.toInt() - 1) != c']' && strHost.lastIndexOf(':') != -1 && + this.flags[INDEX_INVALID]) + { return; } this.analysizeHost(strHost, special); @@ -900,7 +904,7 @@ export namespace url { this.flags[INDEX_INVALID] = true; return; } - if (strHost[strHost.length - 1] != c']') { + if (strHost.charAt(strHost.length.toInt() - 1) != c']') { if ((pos = strHost.lastIndexOf(':')) != -1) { let port: string = strHost.substring(pos + 1); strHost = strHost.substring(0, pos); @@ -932,7 +936,7 @@ export namespace url { private analysizeHostPath(input: string): string { let pos: number = 0; - if (input[input.length - 1] != c']' && (pos = input.lastIndexOf(':')) != -1) { + if (input.charAt(input.length.toInt() - 1) != c']' && (pos = input.lastIndexOf(':')) != -1) { let port: string = input.substring(pos + 1); input = input.substring(0, pos); this.analysizePort(port); @@ -958,7 +962,7 @@ export namespace url { this.analysizeFilescheme(input); return; } - if (input[0] == c'/' && input[1] == c'/' && input[2] != c'/') { + if (input.charAt(0) == c'/' && input.charAt(1) == c'/' && input.charAt(2) != c'/') { let hostAndPath: string = input.substring(2); if (hostAndPath.length == 0) { return; @@ -978,12 +982,14 @@ export namespace url { return; } let pos: number = 0; - if (strHost[strHost.length - 1] != c']' && (pos = strHost.lastIndexOf(':')) != -1) { + if (strHost.charAt(strHost.length.toInt() - 1) != c']' && (pos = strHost.lastIndexOf(':')) != -1) { let port: string = strHost.substring(pos + 1); strHost = strHost.substring(0, pos); this.analysizePort(port); } - if (strHost[strHost.length - 1] != c']' && (pos = strHost.lastIndexOf(':')) != -1 && this.flags[INDEX_INVALID]) { + if (strHost.charAt(strHost.length.toInt() - 1) != c']' && (pos = strHost.lastIndexOf(':')) != -1 && + this.flags[INDEX_INVALID]) + { return; } this.analysizeHost(strHost, special); @@ -994,7 +1000,7 @@ export namespace url { strHost = this.analysizeHostPath(strHost); this.analysizeHost(strHost, special); } - } else if (input[0] == c'/' && input[1] == c'/') { + } else if (input.charAt(0) == c'/' && input.charAt(1) == c'/') { let strOfPath = input.substring(1); this.analysizePath(strOfPath, false); } else { @@ -1007,7 +1013,7 @@ export namespace url { let pos: number = 0; let inputLen: number = input.length; while (pos < inputLen) { - if (input[pos] == c'/' || input[pos] == c'\\') { + if (input.charAt(pos.toInt()) == c'/' || input.charAt(pos.toInt()) == c'\\') { pos++; continue; } @@ -1025,7 +1031,7 @@ export namespace url { } else { let inputLen: number = input.length; if (inputLen > 0) { - this.cIsSpecialPath = input[0] != c'/'; + this.cIsSpecialPath = input.charAt(0) != c'/'; } if (this.flags[INDEX_DOUBLE_SLASH] && inputLen == 2) { return; @@ -1043,7 +1049,7 @@ export namespace url { if (tempInput.indexOf(':') != -1) { let pos = tempInput.indexOf(':'); pos++; - this.flags[INDEX_DOUBLE_SLASH] = (input[pos] == c'/' && input[pos + 1] == c'/'); + this.flags[INDEX_DOUBLE_SLASH] = (input.charAt(pos.toInt()) == c'/' && input.charAt(pos.toInt() + 1) == c'/'); let scheme: string = tempInput.substring(0, pos); if (!this.analysizeScheme(scheme)) { return tempInput; @@ -1093,10 +1099,10 @@ export namespace url { } toolHasBase(input: string, strInput: string): string { - if (input.length != 0 && input[0] == c'/') { + if (input.length != 0 && input.charAt(0) == c'/') { strInput = input.substring(1); return this.analysizeInput(strInput); - } else if (input.length != 0 && input[0] != c'/') { + } else if (input.length != 0 && input.charAt(0) != c'/') { return this.analysizeInput(strInput); } return strInput; @@ -1129,7 +1135,10 @@ export namespace url { let strHost: string = input; let len: number = strHost.length; for (let pos = 0; pos < len; pos++) { - if ((strHost[pos] == c':') || (strHost[pos] == c'?') || (strHost[pos] == c'#') || (strHost[pos] == c'/' || strHost[pos] == c'\\')) { + if ((strHost.charAt(pos.toInt()) == c':') || (strHost.charAt(pos.toInt()) == c'?') || + (strHost.charAt(pos.toInt()) == c'#') || + (strHost.charAt(pos.toInt()) == c'/' || strHost.charAt(pos.toInt()) == c'\\')) + { strHost = strHost.substring(0, pos); break; } @@ -1199,7 +1208,7 @@ export namespace url { this.cFragment = ""; this.flags[INDEX_FRAGMENT] = false; } else { - if (input[0] != c'#') { + if (input.charAt(0) != c'#') { temp = '#'; temp += encodePercentEncoding(input, Helper.FRAGMENT_PERCENT_SIGN_CHARS); } else { @@ -1215,7 +1224,7 @@ export namespace url { this.cQuery = ""; this.flags[INDEX_QUERY] = false; } else { - if (input[0] != c'?') { + if (input.charAt(0) != c'?') { temp = "?"; temp += input; } else { @@ -1241,9 +1250,11 @@ export namespace url { // splitString let strLen: number = input.length; for (let pos = 0; pos < strLen; pos++) { - if ((input[pos] == c':') || (input[pos] == c'?') || (input[pos] == c'#') || (input[pos] == c'/') || (input[pos] == c'\\')) { + if ((input.charAt(pos.toInt()) == c':') || (input.charAt(pos.toInt()) == c'?') || + (input.charAt(pos.toInt()) == c'#') || (input.charAt(pos.toInt()) == c'/') || (input.charAt(pos.toInt()) == c'\\')) + { strHost = input.substring(0, pos); - if (input[pos] == c':') { + if (input.charAt(pos.toInt()) == c':') { pos++; port = input.substring(pos); } @@ -1269,7 +1280,9 @@ export namespace url { if (port.length > 0) { let portLen: number = port.length; for (let pos = 0; pos < portLen; pos++) { - if (port[pos] == c'?' || port[pos] == c'#' || port[pos] == c'/' || port[pos] == c'\\') { + if (port.charAt(pos.toInt()) == c'?' || port.charAt(pos.toInt()) == c'#' || + port.charAt(pos.toInt()) == c'/' || port.charAt(pos.toInt()) == c'\\') + { port = port.substring(0, pos); break; } @@ -1289,7 +1302,9 @@ export namespace url { let port: string = input; let portLen: number = port.length; for (let pos = 0; pos < portLen; pos++) { - if ((port[pos] == c'?') || (port[pos] == c'#') || (port[pos] == c'/') || (port[pos] == c'\\')) { + if ((port.charAt(pos.toInt()) == c'?') || (port.charAt(pos.toInt()) == c'#') || + (port.charAt(pos.toInt()) == c'/') || (port.charAt(pos.toInt()) == c'\\')) + { port = port.substring(0, pos); break; } @@ -1335,7 +1350,7 @@ export namespace url { let special: boolean = Helper.head.has(this.cScheme); if (this.cScheme == "file:") { let tempUrl: InnerURL = new InnerURL(); - if ((strPath[0] == c'/') || (strPath[0] == c'\\' && this.flags[INDEX_SPECIAL])) { + if ((strPath.charAt(0) == c'/') || (strPath.charAt(0) == c'\\' && this.flags[INDEX_SPECIAL])) { strPath = strPath.substring(1); } tempUrl.analysizeFilePath(strPath); @@ -1345,7 +1360,7 @@ export namespace url { } } else { let tempUrl: InnerURL = new InnerURL(); - if ((strPath[0] == c'/') || (strPath[0] == c'\\' && this.flags[INDEX_SPECIAL])) { + if ((strPath.charAt(0) == c'/') || (strPath.charAt(0) == c'\\' && this.flags[INDEX_SPECIAL])) { strPath = strPath.substring(1); } tempUrl.analysizePath(strPath, special); @@ -1490,8 +1505,8 @@ export namespace url { return; } - let ch: char = baseUrl.cPath[0][0]; - let ch1: char = baseUrl.cPath[0][1]; + let ch: char = baseUrl.cPath[0].charAt(0); + let ch1: char = baseUrl.cPath[0].charAt(1); if ((baseUrl.cPath.length == 1) && isFile && Char.isLetter(ch) && ch1 == c':') { return; } @@ -1930,7 +1945,7 @@ export namespace url { result.urlInner = resUrl; return result; } - if ((input[0] == c'/') && (input[1] == c'/' || (input[1] == c'\\' && possibleBaseURL.flags[INDEX_SPECIAL]))) { + if ((input.charAt(0) == c'/') && (input.charAt(1) == c'/' || (input.charAt(1) == c'\\' && possibleBaseURL.flags[INDEX_SPECIAL]))) { let newInput: string = possibleBaseURL.cScheme + input; resUrl.flags[INDEX_INVALID] = false resUrl.parseSingleUrl(newInput); @@ -1941,11 +1956,11 @@ export namespace url { resUrl.flags[INDEX_INVALID] = false baseIntoUrl(possibleBaseURL, resUrl, input.length == 0); strInput = resUrl.toolHasBase(input, strInput); - if (input.length != 0 && input[0] != c'/' && resUrl.cPath.length == 0) { + if (input.length != 0 && input.charAt(0) != c'/' && resUrl.cPath.length == 0) { resUrl.cPath = possibleBaseURL.cPath; resUrl.flags[INDEX_PATH] = possibleBaseURL.flags[INDEX_PATH]; } - if (input.length != 0 && input[0] != c'/' && resUrl.cPath.length != 0) { + if (input.length != 0 && input.charAt(0) != c'/' && resUrl.cPath.length != 0) { let isFile: boolean = resUrl.cScheme == "file:"; shorteningPath(resUrl, possibleBaseURL, isFile); let basePathStr: string = basePathToString(possibleBaseURL); @@ -1974,7 +1989,7 @@ export namespace url { return result; } if (input.length != 0) { - if ((input[0] == c'/') && (input[1] == c'/' || (input[1] == c'\\' && base.flags[INDEX_SPECIAL]))) { + if ((input.charAt(0) == c'/') && (input.charAt(1) == c'/' || (input.charAt(1) == c'\\' && base.flags[INDEX_SPECIAL]))) { let newInput: string = base.cScheme + input; resUrl.flags[INDEX_INVALID] = false resUrl.initOnlyInput(newInput); @@ -1986,11 +2001,11 @@ export namespace url { resUrl.flags[INDEX_INVALID] = false baseIntoUrl(base, resUrl, input.length == 0); strInput = resUrl.toolHasBase(input, strInput); - if (input.length != 0 && input[0] != c'/' && resUrl.cPath.length == 0) { + if (input.length != 0 && input.charAt(0) != c'/' && resUrl.cPath.length == 0) { resUrl.cPath = base.cPath; resUrl.flags[INDEX_PATH] = base.flags[INDEX_PATH]; } - if (input.length != 0 && input[0] != c'/' && resUrl.cPath.length != 0) { + if (input.length != 0 && input.charAt(0) != c'/' && resUrl.cPath.length != 0) { let isFile: boolean = resUrl.cScheme == "file:"; shorteningPath(resUrl, base, isFile); let basePathStr: string = basePathToString(base); @@ -2417,7 +2432,7 @@ export namespace url { } function parseParamFromString(input: string): Array { - if (input[0] == c'?') { + if (input.charAt(0) == c'?') { input = input.slice(1); } let strVal = input.replaceAll('+', ' '); @@ -2599,7 +2614,7 @@ export namespace url { let buf = ""; let i = 0; for (; i < stringParm.length; i++) { - let code = stringParm[i]; + let code = stringParm.charAt(i); switch (code) { case c'&': { diff --git a/static_core/plugins/ets/sdk/api/@ohos.util.ets b/static_core/plugins/ets/sdk/api/@ohos.util.ets index 8ae5f885e3..5e0e5f072a 100644 --- a/static_core/plugins/ets/sdk/api/@ohos.util.ets +++ b/static_core/plugins/ets/sdk/api/@ohos.util.ets @@ -296,7 +296,7 @@ export namespace util { let bytes: Array = new Array(); for (let i = 0; i < cleaned.length; i++) { - let ch = cleaned[i]; + let ch = cleaned.charAt(i); if (ch == c'=') { break; } diff --git a/static_core/plugins/ets/sdk/api/@ohos.xml.ets b/static_core/plugins/ets/sdk/api/@ohos.xml.ets index 475f638093..02d278697e 100644 --- a/static_core/plugins/ets/sdk/api/@ohos.xml.ets +++ b/static_core/plugins/ets/sdk/api/@ohos.xml.ets @@ -442,7 +442,7 @@ export namespace xml { let iLenTemp = tempString.length; if (this.iPos + iLenTemp <= MaxXmlLength) { for (let i = 0; i < iLenTemp; i++) { - this.buffer.set((i + this.iPos) as int, tempString[i].toByte()); + this.buffer.set((i + this.iPos) as int, tempString.charAt(i).toByte()); } this.iPos += iLenTemp; } else { @@ -1242,10 +1242,10 @@ export namespace xml { if (this.buffer.byteLength > this.iPos + iLenTemp - BufferIndexOffset) { for (let i = 0; i < iLenTemp; i++) { if (this.buffer instanceof ArrayBuffer) { - (this.buffer as ArrayBuffer).set((i + this.iPos) as int, tempString[i].toByte()); + (this.buffer as ArrayBuffer).set((i + this.iPos) as int, tempString.charAt(i).toByte()); } else { ((this.buffer as DataView).buffer as ArrayBuffer).set((i + this.iPos) as int, - tempString[i].toByte()); + tempString.charAt(i).toByte()); } } this.iPos += iLenTemp; diff --git a/static_core/plugins/ets/stdlib/std/core/String.ets b/static_core/plugins/ets/stdlib/std/core/String.ets index be0fbd1be7..55340b82ca 100644 --- a/static_core/plugins/ets/stdlib/std/core/String.ets +++ b/static_core/plugins/ets/stdlib/std/core/String.ets @@ -93,7 +93,7 @@ export final class String extends Object implements Comparable, Iterable * * @returns a primitive at index */ - public $_get(index: number): char { + public $_get(index: number): String { return this.$_get(index.toInt()); } @@ -102,11 +102,11 @@ export final class String extends Object implements Comparable, Iterable * * @param index index to look at * - * @returns char value at index + * @returns String value at index * * @throws StringIndexOutOfBoundsError if index is negative or >= length */ - public native $_get(index: int): char; + public native $_get(index: int): String; /** * Checks equality of this string and another Object as String diff --git a/static_core/plugins/ets/tests/checked/ets_string_get.ets b/static_core/plugins/ets/tests/checked/ets_string_get.ets index 87a86fe509..31e7190356 100644 --- a/static_core/plugins/ets/tests/checked/ets_string_get.ets +++ b/static_core/plugins/ets/tests/checked/ets_string_get.ets @@ -17,24 +17,18 @@ //! RUN force_jit: true, options: "", entry: "ets_string_get.ETSGLOBAL::main" //! METHOD "ets_string_get.ETSGLOBAL::main" //! PASS_AFTER "IrBuilder" -//! INST_NOT "Intrinsic.StdCoreStringGet" -//! INST /NullCheck/ -//! INST /BoundsCheck/ -//! INST /LoadCompressedStringChar/ +//! INST "Intrinsic.StdCoreStringGet" //! CHECKER AOT IR Builder StringGet get inlining. //! RUN_PAOC options: "--compiler-regex='.*main.*'" //! METHOD "ets_string_get.ETSGLOBAL::main" //! PASS_AFTER "IrBuilder" -//! INST_NOT /Intrinsic.StdCoreStringGet/ -//! INST /NullCheck/ -//! INST /BoundsCheck/ -//! INST /LoadCompressedStringChar/ +//! INST /Intrinsic.StdCoreStringGet/ function main(): void { let str = "abcdefg"; - arktest.assertEQ(str[0], c'a', "Wrong str.get(0)"); - arktest.assertEQ(str[6], c'g', "Wrong str.get(6)"); + arktest.assertEQ(str[0], "a", "Wrong str.get(0)"); + arktest.assertEQ(str[6], "g", "Wrong str.get(6)"); let exceptionFlag = 0; try { diff --git a/static_core/plugins/ets/tests/ets_func_tests/std/core/StringGetTest.ets b/static_core/plugins/ets/tests/ets_func_tests/std/core/StringGetTest.ets new file mode 100644 index 0000000000..7b766e1c94 --- /dev/null +++ b/static_core/plugins/ets/tests/ets_func_tests/std/core/StringGetTest.ets @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main(): int { + const suite = new arktest.ArkTestsuite('Sting API test for SDK'); + suite.addTest('stringGetTest1', stringGetTest1); + suite.addTest('stringGetTest2', stringGetTest2); + suite.addTest('stringGetTest3', stringGetTest3); + suite.addTest('stringGetTest4', stringGetTest4); + suite.addTest('stringGetTest5', stringGetTest5); + suite.addTest('stringGetTest6', stringGetTest6); + suite.addTest('stringGetTest7', stringGetTest7); + return suite.run() +} + +function stringGetTest1() { + let str: string = 'abcd' + arktest.assertEQ(str[0], 'a') + arktest.assertEQ(str[1], 'b') + arktest.assertEQ(str[2], 'c') + arktest.assertEQ(str[3], 'd') +} + +function stringGetTest2() { + let str: string = 'abcd' + arktest.assertEQ(typeof str[0], 'string') + arktest.assertEQ(typeof str[1], 'string') + arktest.assertEQ(typeof str[2], 'string') + arktest.assertEQ(typeof str[3], 'string') +} + +function stringGetTest3() { + let str: string = 'abcd' + arktest.assertEQ(typeof str[0 as number], 'string') + arktest.assertEQ(typeof str[1 as number], 'string') + arktest.assertEQ(typeof str[2 as number], 'string') + arktest.assertEQ(typeof str[3 as number], 'string') +} + +function stringGetTest4() { + let str: string = 'abcd' + arktest.assertEQ(str[0 as number], 'a') + arktest.assertEQ(str[1 as number], 'b') + arktest.assertEQ(str[2 as number], 'c') + arktest.assertEQ(str[3 as number], 'd') +} + +function stringGetTest5() { + const str: string = '\0\u2028πŸ˜€δΈ­ζ–‡'; + + arktest.assertEQ(str[0], '\0'); + arktest.assertEQ(str[1], '\u2028'); + + arktest.assertEQ(str.length, 6); + arktest.assertEQ(str[2], '\uD83D'); + arktest.assertEQ(str[3], '\uDE00'); + + arktest.assertEQ(str[4], 'δΈ­'); + arktest.assertEQ(str[5], 'ζ–‡'); +} + +function stringGetTest6(): void { + const str: string = "AΞ±γ‚πŸ˜€πŸŒ"; + + arktest.assertEQ(str.length, 7); + arktest.assertEQ(str[0], 'A'); + arktest.assertEQ(str[1], 'Ξ±'); + arktest.assertEQ(str[2], 'あ'); + arktest.assertEQ(str[3]+str[4], 'πŸ˜€'); + arktest.assertEQ(str.slice(5,7), '🌍'); +} + +function stringGetTest7() { + let str: string = 'abcd' + let exceptionFlag = 0; + try { + console.log(str[-1]); + } catch (e: StringIndexOutOfBoundsError) { + exceptionFlag = 1; + } catch (e) { + exceptionFlag = 2; + } + arktest.assertEQ(1, exceptionFlag); + + try { + console.log(str[4]); + } catch (e: StringIndexOutOfBoundsError) { + exceptionFlag = 1; + } catch (e) { + exceptionFlag = 2; + } + arktest.assertEQ(1, exceptionFlag); +} \ No newline at end of file diff --git a/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/GenerateRandomUUIDTest.ets b/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/GenerateRandomUUIDTest.ets index a002fabeac..df3720d0a7 100644 --- a/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/GenerateRandomUUIDTest.ets +++ b/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/GenerateRandomUUIDTest.ets @@ -42,17 +42,17 @@ function testGenerateRandomUUID(): int { const hexDigits = "0123456789abcdef" for (let i = 0; i < 36; ++i) { if (delimiterIdx.includes(i)) { - arktest.assertEQ(id[i], c'-') + arktest.assertEQ(id.charAt(i), c'-') } else { - arktest.assertTrue(hexDigits.includes(new Char(id[i]).toString())) + arktest.assertTrue(hexDigits.includes(new Char(id.charAt(i)).toString())) } } const versionByte = 14 - arktest.assertEQ(id[versionByte], c'4', "Version byte has to be 0x4") + arktest.assertEQ(id.charAt(versionByte), c'4', "Version byte has to be 0x4") const withReservedBits = 19 - arktest.assertTrue(id[withReservedBits] >= c'8' && id[withReservedBits] <= c'b', - id[withReservedBits] + " are not valid reserved bits from range 0x8..0xb!") + arktest.assertTrue(id.charAt(withReservedBits) >= c'8' && id.charAt(withReservedBits) <= c'b', + id.charAt(withReservedBits) + " are not valid reserved bits from range 0x8..0xb!") return success } diff --git a/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/TextEncoderTest.ets b/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/TextEncoderTest.ets index 6bd9ed7fca..4925302ac9 100644 --- a/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/TextEncoderTest.ets +++ b/static_core/plugins/ets/tests/ets_sdk/api/@ohos/util/TextEncoderTest.ets @@ -15,9 +15,9 @@ import {util} from "@ohos.util"; -function NumberEqual(resStr:number, expect:number) +function CharCodeEqual(resStr: String, expect: number) { - return resStr === expect; + return resStr.charCodeAt(0) === expect; } function main() { @@ -51,7 +51,8 @@ function test_encoder_utf8() let str = 'Hello world'; const bytes = enc.encodeInto(str); for (let i = 0; i < str.length; i++) { - arktest.assertTrue(NumberEqual(bytes[i], str[i]), "expected equality failed: " + bytes[i] + "===" + str[i]); + arktest.assertTrue(CharCodeEqual(str[i], bytes[i]), "expected equality failed: " + + str[i].charCodeAt(0) + "===" + bytes[i]); } } diff --git a/static_core/plugins/ets/tests/ets_test_suite/strings/string_api.ets b/static_core/plugins/ets/tests/ets_test_suite/strings/string_api.ets index be9ada4104..6dd03f6c5d 100644 --- a/static_core/plugins/ets/tests/ets_test_suite/strings/string_api.ets +++ b/static_core/plugins/ets/tests/ets_test_suite/strings/string_api.ets @@ -136,9 +136,9 @@ function main(): void { arktest.assertEQ(arr.length, 3, "Length must be 3"); let str4: String = "Example string"; - arktest.assertEQ(str4[0], c'E', "First character must be `E`"); - arktest.assertEQ(str4[8], c's', "Eighth character must be `s`"); - arktest.assertEQ(str4[str4.length - 1], c'g', "Last character must be `g`"); + arktest.assertEQ(str4[0], "E", "First character must be `E`"); + arktest.assertEQ(str4[8], "s", "Eighth character must be `s`"); + arktest.assertEQ(str4[str4.length - 1], "g", "Last character must be `g`"); let exceptionCheck = (e: Error | Exception): boolean | string => { return (e instanceof StringIndexOutOfBoundsError); @@ -155,5 +155,5 @@ function main(): void { }, exceptionCheck); let str5: String = "函数式编程"; - arktest.assertEQ(str5[0], c'函', "First character must be `函`"); + arktest.assertEQ(str5[0], "函", "First character must be `函`"); } -- Gitee