diff --git a/ecmascript/base/json_stringifier.cpp b/ecmascript/base/json_stringifier.cpp index 02ef7a5ed2b40b27c683b26dde3f6d75c88875df..d683907946293336bcb14500ed85e72a740ada45 100644 --- a/ecmascript/base/json_stringifier.cpp +++ b/ecmascript/base/json_stringifier.cpp @@ -699,6 +699,9 @@ bool JsonStringifier::SerializeElements(const JSHandle &obj, const JSH JSTaggedValue entryKey = entry.GetTaggedValue(); handleKey_.Update(entryKey); int index = numberDic->FindEntry(entryKey); + if (index < 0) { + continue; + } JSTaggedValue value = numberDic->GetValue(index); if (UNLIKELY(value.IsAccessor())) { value = JSObject::CallGetter(thread_, AccessorData::Cast(value.GetTaggedObject()), @@ -773,14 +776,14 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl if (UNLIKELY(value.IsAccessor())) { value = JSObject::CallGetter(thread_, AccessorData::Cast(value.GetTaggedObject()), JSHandle(obj)); - if (obj->GetProperties().IsDictionary()) { - hasChangedToDictionaryMode = true; - propertiesArr = JSHandle(thread_, obj->GetProperties()); - } - jsHclass = JSHandle(thread_, obj->GetJSHClass()); } handleValue_.Update(value); hasContent = JsonStringifier::AppendJsonString(obj, replacer, hasContent); + if (obj->GetProperties().IsDictionary()) { + hasChangedToDictionaryMode = true; + propertiesArr = JSHandle(thread_, obj->GetProperties()); + } + jsHclass = JSHandle(thread_, obj->GetJSHClass()); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); } } else { diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index 7297f0ce28f3d290a35fd8c8aa4876aad7686240..92656646e1661e57f3f28bc173be2cfc86cf09a8 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -102,7 +102,7 @@ JSTaggedValue NumberHelper::DoubleToString(JSThread *thread, double number, int auto value = bit_cast(number); value += 1; double delta = HALF * (bit_cast(value) - number); - + delta = std::max(delta, bit_cast(static_cast(1))); // 1 : The binary of the smallest double is 1 CString result; if (numberFraction != 0 && numberFraction >= delta) { result += "."; diff --git a/ecmascript/builtins/builtins_string.cpp b/ecmascript/builtins/builtins_string.cpp index 218a5d1daf1a25f507276ac8dbe7822c767c0a47..44605e0e94d1e3e76a3a78cb9e90d6405feaf78a 100644 --- a/ecmascript/builtins/builtins_string.cpp +++ b/ecmascript/builtins/builtins_string.cpp @@ -1225,7 +1225,7 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle captureName(capture); + JSHandle captureName = JSTaggedValue::ToString(thread, capture); stringBuilder += EcmaStringAccessor(captureName).ToU16String(); if (EcmaStringAccessor(captureName).IsUtf16()) { canBeCompress = false; diff --git a/ecmascript/js_proxy.cpp b/ecmascript/js_proxy.cpp index a249dd9801e7c93a580ac55e8f46f7420d59e409..8726597ae00e379839825d57ea5f550ff80c40a0 100644 --- a/ecmascript/js_proxy.cpp +++ b/ecmascript/js_proxy.cpp @@ -609,6 +609,17 @@ OperationResult JSProxy::GetProperty(JSThread *thread, const JSHandle & bool JSProxy::SetProperty(JSThread *thread, const JSHandle &proxy, const JSHandle &key, const JSHandle &value, const JSHandle &receiver, bool mayThrow) { + // check stack overflow because infinite recursion may occur + if (thread->IsAsmInterpreter() && UNLIKELY(thread->GetCurrentStackPosition() < thread->GetStackLimit())) { + LOG_ECMA(ERROR) << "Stack overflow! current:" << thread->GetCurrentStackPosition() + << " limit:" << thread->GetStackLimit(); + if (LIKELY(!thread->HasPendingException())) { + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle error = factory->GetJSError(base::ErrorType::RANGE_ERROR, "Stack overflow!", false); + thread->SetException(error.GetTaggedValue()); + } + return false; + } const GlobalEnvConstants *globalConst = thread->GlobalConstants(); // step 1 ~ 10 are almost same as GetOwnProperty ASSERT(JSTaggedValue::IsPropertyKey(key)); diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 70f9c5648471f272ba46b2c63b84f72d418ccbd5..3a513c43824d02895f752420f06eb3d755adb1ce 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -2382,13 +2382,14 @@ JSTaggedValue RuntimeStubs::RuntimeOptConstructProxy(JSThread *thread, JSHandle< JSTaggedValue value = args->Get(i); arr->Set(thread, i + preArgsSize, value); } + JSHandle newArr = JSArray::CreateArrayFromList(thread, arr); // step 8 ~ 9 Call(trap, handler, «target, argArray, newTarget »). const uint32_t argsLength = 3; // 3: «target, argArray, newTarget » JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - info->SetCallArg(target.GetTaggedValue(), arr.GetTaggedValue(), newTgt.GetTaggedValue()); + info->SetCallArg(target.GetTaggedValue(), newArr.GetTaggedValue(), newTgt.GetTaggedValue()); JSTaggedValue newObjValue = JSFunction::Call(info); // 10.ReturnIfAbrupt(newObj). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index ca18f117e04c33d75e509f01162f9204c02860c7..e97bfc3f83bce03fbbef24a34fe48e34c360ef01 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -93,6 +93,7 @@ group("ark_js_moduletest") { "stackoverflow", "storeicbyname", "string", + "stringreplace", "stubbuilder", "throwdyn", "trycatch", @@ -200,6 +201,7 @@ group("ark_asm_test") { "setobjectwithproto", "spreadoperator", "stackoverflow", + "stringreplace", "stubbuilder", "throwdyn", "trycatch", @@ -298,6 +300,7 @@ group("ark_asm_single_step_test") { "setobjectwithproto", "spreadoperator", "stackoverflow", + "stringreplace", "stubbuilder", "throwdyn", "trycatch", diff --git a/test/moduletest/asmstackoverflow/asmstackoverflow.js b/test/moduletest/asmstackoverflow/asmstackoverflow.js index 5a650d1d1d5b645c9145b3f1eea4e5baa94e7c12..1c79a445157210ff60317af451e91daf2799513d 100644 --- a/test/moduletest/asmstackoverflow/asmstackoverflow.js +++ b/test/moduletest/asmstackoverflow/asmstackoverflow.js @@ -40,4 +40,13 @@ try { if (e instanceof RangeError) { print("proxy stackoverflow!"); } -} \ No newline at end of file +} +try { + function func() { } + Function.prototype.__proto__ = new Proxy(func, {}) + Function.prototype.__proto__ = new Proxy(func, {}) +} catch (error) { + if (error instanceof RangeError) { + print("proxy stackoverflow2!"); + } +} diff --git a/test/moduletest/asmstackoverflow/expect_output.txt b/test/moduletest/asmstackoverflow/expect_output.txt index be2162686994fd0df7a69591199226adbe4724c6..ad4466c55c7b358ca79422b64e466b289cbb8e75 100644 --- a/test/moduletest/asmstackoverflow/expect_output.txt +++ b/test/moduletest/asmstackoverflow/expect_output.txt @@ -13,3 +13,4 @@ stack overflow2! proxy stackoverflow! +proxy stackoverflow2! diff --git a/test/moduletest/builtins/builtinsnumber.js b/test/moduletest/builtins/builtinsnumber.js index 8fdd1f07154ccc8434ce0cb74f5f531f25373da7..74e04f73fc9f486b4ec8c90350b81a8c74fc619e 100644 --- a/test/moduletest/builtins/builtinsnumber.js +++ b/test/moduletest/builtins/builtinsnumber.js @@ -33,4 +33,7 @@ try { print(e); }; +var s = (2.2250738585072e-308).toString(36) +print(s) + print("builtins number end"); \ No newline at end of file diff --git a/test/moduletest/builtins/expect_output.txt b/test/moduletest/builtins/expect_output.txt index efefb9595586f5150b6a227154092d2ca1af6906..69c3b299ca07e5cdc09cd471117e5b1cc8798fab 100644 --- a/test/moduletest/builtins/expect_output.txt +++ b/test/moduletest/builtins/expect_output.txt @@ -38,6 +38,7 @@ parseInt result = 16947500000 0.7999999999999999 -Infinity TypeError: Cannot convert a BigInt value to a number +0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034lmua2oev builtins number end builtins regexp start 20210608_5V0J5lVh4xVNYx0AUE.jpg,.jpg diff --git a/test/moduletest/jsonstringifier/expect_output.txt b/test/moduletest/jsonstringifier/expect_output.txt index 14b5531aa0f95c41ebf6d1e238f006ecf1f557f8..ec97dc89fff95956dc7256d29c1411c594b17a76 100644 --- a/test/moduletest/jsonstringifier/expect_output.txt +++ b/test/moduletest/jsonstringifier/expect_output.txt @@ -16,3 +16,5 @@ test successful {"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0} {"g":9,"f1":1,"f2":1,"f3":1,"f4":1,"f5":1,"f6":1,"f7":1,"f8":1} {"g":8,"f2":1} +{"a":{}} +{"3":3} diff --git a/test/moduletest/jsonstringifier/jsonstringifier.js b/test/moduletest/jsonstringifier/jsonstringifier.js index 482c9129f84244c77d28bf249d4dfeb0ea522136..f1c03908fe85c604b92527a18c0d512a3e5f7646 100644 --- a/test/moduletest/jsonstringifier/jsonstringifier.js +++ b/test/moduletest/jsonstringifier/jsonstringifier.js @@ -65,4 +65,22 @@ let o2 = { "f1":1, "f2":1, } -print(JSON.stringify(o2)) \ No newline at end of file +print(JSON.stringify(o2)) +var handler2 = { + get:function(target,name) { + delete parent2.c; + return name.toUpperCase(); + }, +} +var proxy2 = new Proxy({},handler2); +var parent2 = {a:proxy2,c:"remove"}; +print(JSON.stringify(parent2)) + +var obj={ + get 1() { + delete this['2']; + }, + 2:2, + 3:3, +} +print(JSON.stringify(obj)) \ No newline at end of file diff --git a/test/moduletest/proxy/expect_output.txt b/test/moduletest/proxy/expect_output.txt index 7c6fdaefcc3de11e27411883166bc023149f15b4..a8f9169d72e4aa2aaa545f4ffee1ed15772f53c6 100644 --- a/test/moduletest/proxy/expect_output.txt +++ b/test/moduletest/proxy/expect_output.txt @@ -20,3 +20,4 @@ name name name 1,2,3,4 +undefined diff --git a/test/moduletest/proxy/proxy.js b/test/moduletest/proxy/proxy.js index e3275799612a7b71bbe66d6172b8b38f125f69ca..17ef222c6f5ba8363b5856302fa878ac588fdac5 100644 --- a/test/moduletest/proxy/proxy.js +++ b/test/moduletest/proxy/proxy.js @@ -62,3 +62,13 @@ const handler = {}; const proxy = new Proxy(arr2, handler); const arr3 = proxy.constructor(1, 2, 3, 4); print(arr3); + +function Target() {} +var handler1 = { + construct: function(t, args) { + return new t(args[0], args[1]); + } +}; +var P = new Proxy(Target, handler1); +new P(1, 1.1); +print(JSON.stringify(P)); diff --git a/test/moduletest/stringreplace/BUILD.gn b/test/moduletest/stringreplace/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..14354b0f9bbcff1d5808231897bb5ae4860400d6 --- /dev/null +++ b/test/moduletest/stringreplace/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2023 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. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("stringreplace") { + deps = [] +} diff --git a/test/moduletest/stringreplace/expect_output.txt b/test/moduletest/stringreplace/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..b4d4c241d3f5ef1ee7e8827bdeafbd0970fb8c6e --- /dev/null +++ b/test/moduletest/stringreplace/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2023 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. + +[1.1] diff --git a/test/moduletest/stringreplace/stringreplace.js b/test/moduletest/stringreplace/stringreplace.js new file mode 100644 index 0000000000000000000000000000000000000000..ec2d77d0268804fb9af76b9585619cdb8346806e --- /dev/null +++ b/test/moduletest/stringreplace/stringreplace.js @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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. + */ + +/* + * @tc.name:storeicbyname + * @tc.desc:test storeicbyname + * @tc.type: FUNC + * @tc.require: issueI7UTOA + */ + +var r = /./; +var coercibleValue = { + length: 1, + groups: {length : 1.1}, +}; +r.exec = function() { + return coercibleValue; +}; +let a = r[Symbol.replace]('', '[$]'); +print(a)