diff --git a/ecmascript/builtins/builtins_function.cpp b/ecmascript/builtins/builtins_function.cpp index f1f0e01c3809e3cc503e7de990c2e941ea36569b..705d80865ae0b8f21b7cefb4817bfe093a291a15 100644 --- a/ecmascript/builtins/builtins_function.cpp +++ b/ecmascript/builtins/builtins_function.cpp @@ -43,12 +43,17 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeInvokeSelf([[maybe_unused]] Ecm return JSTaggedValue::Undefined(); } namespace { -static size_t MakeArgListWithHole(JSThread *thread, TaggedArray *argv, size_t length) +static size_t MakeArgListWithHole(JSThread *thread, TaggedArray *argv, int length) { - if (length > argv->GetLength()) { - length = argv->GetLength(); + if (length <= 0) { + return 0; } - for (size_t index = 0; index < length; ++index) { + size_t newlength = static_cast(length); + size_t arryLength = argv->GetLength(); + if (newlength > arryLength) { + length = arryLength; + } + for (size_t index = 0; index < newlength; ++index) { JSTaggedValue value = argv->Get(thread, index); if (value.IsHole()) { argv->Set(thread, index, JSTaggedValue::Undefined()); @@ -74,7 +79,7 @@ static std::pair BuildArgumentsListFast(JSThread *thread, if (!result.IsInt()) { return std::make_pair(nullptr, 0); } - size_t length = static_cast(result.GetInt()); + auto length = result.GetInt(); size_t res = MakeArgListWithHole(thread, elements, length); return std::make_pair(elements, res); } else if (arrayObj->IsStableJSArray(thread)) { diff --git a/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp b/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp index f8853e730040be290298625a39fdcd67176608a6..aa49f9088ba978125f28b86aa25a5603aea64a39 100644 --- a/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp +++ b/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp @@ -1205,7 +1205,21 @@ void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(ExtendedAssembler if (glue != r13) { __ Movq(glue, r13); } - __ Callq(op); + __ Pushq(rbp); + __ Pushq(static_cast(FrameType::ASM_BRIDGE_FRAME)); // set frame type + __ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // skip frame type + + __ Pushq(r10); // caller save + __ Pushq(0); // argc + __ Pushq(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException); // runtime id + __ Movq(glue, rax); // glue + __ Movq(kungfu::RuntimeStubCSigns::ID_CallRuntime, r10); + __ Movq(Operand(rax, r10, Times8, JSThread::GlueData::GetRTStubEntriesOffset(false)), r10); + __ Callq(r10); // call CallRuntime + __ Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip argc and runtime_id + __ Popq(r10); + __ Addq(FRAME_SLOT_SIZE, rsp); // skip frame type + __ Popq(rbp); __ Ret(); } diff --git a/ecmascript/js_object-inl.h b/ecmascript/js_object-inl.h index ab9027aa86478110d118d2ca6c165c73ac8bba4a..f8488fe74e0656cfc3eb51dd8600b3ff07aee12c 100644 --- a/ecmascript/js_object-inl.h +++ b/ecmascript/js_object-inl.h @@ -367,6 +367,14 @@ JSHandle JSObject::CreateListFromArrayLike(JSThread *thread, cons THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike must accept object", JSHandle(thread, JSTaggedValue::Exception())); } + if (obj->IsTypedArray()) { + uint32_t len = JSHandle::Cast(obj)->GetArrayLength(); + JSHandle array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len); + JSTypedArray::FastCopyElementToArray(thread, obj, array); + // c. ReturnIfAbrupt(next). + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); + return JSHandle(array); + } // 4. Let len be ToLength(Get(obj, "length")). JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); @@ -383,12 +391,6 @@ JSHandle JSObject::CreateListFromArrayLike(JSThread *thread, cons // 6. Let list be an empty List. JSHandle array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len); - if (obj->IsTypedArray()) { - JSTypedArray::FastCopyElementToArray(thread, obj, array); - // c. ReturnIfAbrupt(next). - RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); - return JSHandle(array); - } // 8. Repeat while index < len for (uint32_t i = 0; i < len; i++) { JSTaggedValue next = JSTaggedValue::GetProperty(thread, obj, i).GetValue().GetTaggedValue(); diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 52a1c1d8912f1b372561a5c9f41b505dde9a7b99..10d2a88424d001714ab6e379a092940ef8e112bf 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -240,9 +240,12 @@ JSTaggedValue RuntimeStubs::RuntimeSuperCallSpread(JSThread *thread, const JSHan { JSHandle superFunc(thread, JSTaggedValue::GetPrototype(thread, func)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - ASSERT(superFunc->IsJSFunction()); + if (!superFunc->IsJSFunction()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Super constructor is not JSFunction", JSTaggedValue::Exception()); + } JSHandle argv(thread, RuntimeGetCallSpreadArgs(thread, array)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); const uint32_t argsLength = argv->GetLength(); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo *info = diff --git a/test/moduletest/asmstackoverflow/asmstackoverflow.js b/test/moduletest/asmstackoverflow/asmstackoverflow.js index 1c79a445157210ff60317af451e91daf2799513d..f9921e9a613703760a7c5b7f5cf1e3ccf16b5511 100644 --- a/test/moduletest/asmstackoverflow/asmstackoverflow.js +++ b/test/moduletest/asmstackoverflow/asmstackoverflow.js @@ -50,3 +50,78 @@ try { print("proxy stackoverflow2!"); } } + +function callarg0_with_callthis() { + const arr = [1] + function bar() { + return 1; + } + arr.filter(bar); + return foo_arg0(); +} + +try { + foo_arg0(); +} catch (e) { + print("callarg0_with_callthis stack overflow!") +} + +function callarg1_with_callthis(a) { + const arr = [1] + function bar() { + return 1; + } + arr.filter(bar); + return callarg1_with_callthis(a); +} + +try { + callarg1_with_callthis(1); +} catch (e) { + print("callarg1_with_callthis stack overflow!") +} + +function callarg2_with_callthis(a, b) { + const arr = [1] + function bar() { + return 1; + } + arr.filter(bar); + return callarg2_with_callthis(a, b); +} + +try { + callarg2_with_callthis(1, 2); +} catch (e) { + print("callarg2_with_callthis stack overflow!") +} + +function callarg3_with_callthis(a, b, c) { + const arr = [1] + function bar() { + return 1; + } + arr.filter(bar); + return callarg3_with_callthis(a, b, c); +} + +try { + callarg3_with_callthis(1, 2, 3); +} catch (e) { + print("callarg3_with_callthis stack overflow!") +} + +function callrange_with_callthis(a, b, c, d) { + const arr = [1] + function bar() { + return 1; + } + arr.filter(bar); + return callrange_with_callthis(a, b, c, d); +} + +try { + callrange_with_callthis(1, 2, 3, 4); +} catch (e) { + print("callrange_with_callthis stack overflow!") +} diff --git a/test/moduletest/asmstackoverflow/expect_output.txt b/test/moduletest/asmstackoverflow/expect_output.txt index ad4466c55c7b358ca79422b64e466b289cbb8e75..df45c6071c0c04acf6a4d054635d0e5c2f92612c 100644 --- a/test/moduletest/asmstackoverflow/expect_output.txt +++ b/test/moduletest/asmstackoverflow/expect_output.txt @@ -14,3 +14,8 @@ stack overflow2! proxy stackoverflow! proxy stackoverflow2! +callarg0_with_callthis stack overflow! +callarg1_with_callthis stack overflow! +callarg2_with_callthis stack overflow! +callarg3_with_callthis stack overflow! +callrange_with_callthis stack overflow! diff --git a/test/moduletest/calltype/calltype.js b/test/moduletest/calltype/calltype.js index afc19c329117be6ce87b2be30e986f8f91e5e2ca..08e51f7a4f3dec7cfc3ff16ae3e65e93c765d608 100644 --- a/test/moduletest/calltype/calltype.js +++ b/test/moduletest/calltype/calltype.js @@ -88,4 +88,36 @@ var b = new String("newobj native"); print(b); obj.type = 555; -print("getter", obj.type); \ No newline at end of file +print("getter", obj.type); + +function test_func7(f) { + function t() { + try { + t(); + } catch (e) { + return f(); + } + } + return t(); +} +class c0 { +} +class c1 extends c0 { +} +function f1(v5, v6) { + return new c1(v5, v6) +} + +Object.defineProperty(Array.prototype, Symbol.iterator, { + value: function* () { }, + configurable: true +}); + +try { + var v1 = test_func7(() => { + return f1(1, 2); + }); + print(v1); +} catch (e) { + print(e); +} \ No newline at end of file diff --git a/test/moduletest/calltype/expect_output.txt b/test/moduletest/calltype/expect_output.txt index 59b6393a9bf55dbe29ba2bad20c9ba5af0779498..7d6923806e3e202cf1e0e02eba18aff6379d53bb 100644 --- a/test/moduletest/calltype/expect_output.txt +++ b/test/moduletest/calltype/expect_output.txt @@ -24,3 +24,4 @@ newobj 2 newobj native setter 555 getter 555 +undefined