From cdba5d43ba592f2f31103a320d4c94e213de46a3 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Sat, 11 May 2024 23:18:52 +0800 Subject: [PATCH] fix napi sendable 1. add ut 2. fix some interface bug https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9OLPG Signed-off-by: wengchangcheng Change-Id: Ic26e5fe5fb39432a896b6a98a8e194006e623bf1 --- ecmascript/base/typed_array_helper-inl.h | 2 +- ecmascript/base/typed_array_helper.cpp | 2 +- ecmascript/base/typed_array_helper.h | 3 +- .../builtins/builtins_shared_typedarray.cpp | 6 +- ecmascript/js_typed_array.cpp | 2 +- ecmascript/js_typed_array.h | 1 - ecmascript/napi/include/jsnapi_expo.h | 34 +++++-- ecmascript/napi/jsnapi_expo.cpp | 88 +++++++++++++++---- ecmascript/object_factory.cpp | 22 ++++- ecmascript/object_factory.h | 2 + .../shared_objects/js_shared_typed_array.h | 2 + libark_jsruntime.map | 3 + test/test_helper.gni | 2 +- 13 files changed, 134 insertions(+), 35 deletions(-) diff --git a/ecmascript/base/typed_array_helper-inl.h b/ecmascript/base/typed_array_helper-inl.h index a4a52ef48a..3adadba432 100644 --- a/ecmascript/base/typed_array_helper-inl.h +++ b/ecmascript/base/typed_array_helper-inl.h @@ -426,7 +426,7 @@ JSHandle TypedArrayHelper::GetNotOnHeapHclassFromType( } JSHandle TypedArrayHelper::GetSharedNotOnHeapHclassFromType( - JSThread *thread, const JSHandle &obj, const DataViewType arrayType) + JSThread *thread, const JSHandle &obj, const DataViewType arrayType) { JSHClass* objHclass = JSHandle(obj)->GetClass(); ASSERT_PRINT(objHclass->IsOnHeapFromBitField(), "must be on heap"); diff --git a/ecmascript/base/typed_array_helper.cpp b/ecmascript/base/typed_array_helper.cpp index 9e742c8312..d2069a0b03 100644 --- a/ecmascript/base/typed_array_helper.cpp +++ b/ecmascript/base/typed_array_helper.cpp @@ -504,7 +504,7 @@ JSTaggedValue TypedArrayHelper::CreateSharedFromTypedArray(EcmaRuntimeCallInfo * // 6. Let srcData be srcArray.[[ViewedArrayBuffer]]. JSTaggedValue buffer; if (srcArray->IsSharedTypedArray()) { - buffer = JSTypedArray::GetSharedOffHeapBuffer(thread, srcObj); + buffer = JSSharedTypedArray::GetSharedOffHeapBuffer(thread, JSHandle(srcObj)); } else { buffer = JSTypedArray::GetOffHeapBuffer(thread, srcObj); } diff --git a/ecmascript/base/typed_array_helper.h b/ecmascript/base/typed_array_helper.h index 9a7dfe03d1..c3e707b0ed 100644 --- a/ecmascript/base/typed_array_helper.h +++ b/ecmascript/base/typed_array_helper.h @@ -21,6 +21,7 @@ #include "ecmascript/base/builtins_base.h" #include "ecmascript/js_dataview.h" #include "ecmascript/js_typed_array.h" +#include "ecmascript/shared_objects/js_shared_typed_array.h" #include "ecmascript/builtins/builtins_shared_typedarray.h" #include "ecmascript/builtins/builtins_typedarray.h" @@ -88,7 +89,7 @@ public: inline static JSHandle GetSharedOnHeapHclassFromType( JSThread *thread, const JSHandle &obj, const DataViewType arrayType); inline static JSHandle GetSharedNotOnHeapHclassFromType( - JSThread *thread, const JSHandle &obj, const DataViewType arrayType); + JSThread *thread, const JSHandle &obj, const DataViewType arrayType); inline static uint32_t GetSizeFromType(const DataViewType arrayType); inline static bool IsAccessorHasChanged(const JSHandle &obj); static int32_t SortCompare(JSThread *thread, const JSHandle &callbackfnHandle, diff --git a/ecmascript/builtins/builtins_shared_typedarray.cpp b/ecmascript/builtins/builtins_shared_typedarray.cpp index c7925cb94a..4f14c06150 100755 --- a/ecmascript/builtins/builtins_shared_typedarray.cpp +++ b/ecmascript/builtins/builtins_shared_typedarray.cpp @@ -375,8 +375,8 @@ JSTaggedValue BuiltinsSharedTypedArray::GetBuffer(EcmaRuntimeCallInfo *argv) THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot. - JSHandle typedArray = JSHandle::Cast(thisHandle); - JSTaggedValue buffer = JSTypedArray::GetSharedOffHeapBuffer(thread, typedArray); + JSHandle typedArray = JSHandle::Cast(thisHandle); + JSTaggedValue buffer = JSSharedTypedArray::GetSharedOffHeapBuffer(thread, typedArray); // 5. Return buffer. return buffer; } @@ -1623,7 +1623,7 @@ JSTaggedValue BuiltinsSharedTypedArray::Subarray(EcmaRuntimeCallInfo *argv) ASSERT((static_cast(srcByteOffset) + static_cast(beginIndex) * static_cast(elementSize)) <= static_cast(UINT32_MAX)); uint32_t beginByteOffset = srcByteOffset + beginIndex * elementSize; - JSTaggedValue buffer = JSTypedArray::GetSharedOffHeapBuffer(thread, thisObj); + JSTaggedValue buffer = JSSharedTypedArray::GetSharedOffHeapBuffer(thread, JSHandle(thisObj)); // 21. Let argumentsList be «buffer, beginByteOffset, newLength». // 5. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot. // 22. Return Construct(constructor, argumentsList). diff --git a/ecmascript/js_typed_array.cpp b/ecmascript/js_typed_array.cpp index 2744c04273..b750d50dd3 100644 --- a/ecmascript/js_typed_array.cpp +++ b/ecmascript/js_typed_array.cpp @@ -776,7 +776,7 @@ JSTaggedValue JSTypedArray::GetOffHeapBuffer(JSThread *thread, JSHandle &typedArray) +JSTaggedValue JSSharedTypedArray::GetSharedOffHeapBuffer(JSThread *thread, JSHandle typedArray) { JSTaggedValue arrBuf = typedArray->GetViewedArrayBufferOrByteArray(); if (arrBuf.IsSendableArrayBuffer()) { diff --git a/ecmascript/js_typed_array.h b/ecmascript/js_typed_array.h index 8559a77fff..59d988154c 100644 --- a/ecmascript/js_typed_array.h +++ b/ecmascript/js_typed_array.h @@ -100,7 +100,6 @@ public: // only use in TypeArray fast set property static JSTaggedNumber NonEcmaObjectToNumber(JSThread *thread, const JSTaggedValue tagged); static JSTaggedValue GetOffHeapBuffer(JSThread *thread, JSHandle &typedArray); - static JSTaggedValue GetSharedOffHeapBuffer(JSThread *thread, JSHandle &typedArray); static bool FastTypedArrayFill(JSThread *thread, const JSHandle &typedArray, const JSHandle &value, uint32_t start, uint32_t end); static constexpr size_t VIEWED_ARRAY_BUFFER_OFFSET = JSObject::SIZE; diff --git a/ecmascript/napi/include/jsnapi_expo.h b/ecmascript/napi/include/jsnapi_expo.h index 9ec8c2c78c..812a539953 100644 --- a/ecmascript/napi/include/jsnapi_expo.h +++ b/ecmascript/napi/include/jsnapi_expo.h @@ -970,12 +970,19 @@ public: void Detach(const EcmaVM *vm); bool IsDetach(); +}; + +class ECMA_PUBLIC_API SendableArrayBufferRef : public ObjectRef { +public: + static Local New(const EcmaVM *vm, int32_t length); + static Local New(const EcmaVM *vm, void *buffer, int32_t length, + const NativePointerCallback &deleter, void *data); - static Local NewSendable(const EcmaVM *vm, int32_t length); + int32_t ByteLength(const EcmaVM *vm); + void *GetBuffer(); - void SendableDetach(const EcmaVM *vm); - bool SendableIsDetach(); - void *SendableGetBuffer(); + void Detach(const EcmaVM *vm); + bool IsDetach(); }; class ECMA_PUBLIC_API DateRef : public ObjectRef { @@ -991,11 +998,14 @@ public: uint32_t ByteOffset(const EcmaVM *vm); uint32_t ArrayLength(const EcmaVM *vm); Local GetArrayBuffer(const EcmaVM *vm); +}; - uint32_t SendableByteLength(const EcmaVM *vm); - uint32_t SendableByteOffset(const EcmaVM *vm); - uint32_t SendableArrayLength(const EcmaVM *vm); - Local SendableGetArrayBuffer(const EcmaVM *vm); +class ECMA_PUBLIC_API SendableTypedArrayRef : public ObjectRef { +public: + uint32_t ByteLength(const EcmaVM *vm); + uint32_t ByteOffset(const EcmaVM *vm); + uint32_t ArrayLength(const EcmaVM *vm); + Local GetArrayBuffer(const EcmaVM *vm); }; class ECMA_PUBLIC_API ArrayRef : public ObjectRef { @@ -1007,6 +1017,14 @@ public: static Local GetValueAt(const EcmaVM *vm, Local obj, uint32_t index); }; +class ECMA_PUBLIC_API SendableArrayRef : public ObjectRef { +public: + static Local New(const EcmaVM *vm, uint32_t length = 0); + uint32_t Length(const EcmaVM *vm); + static bool SetValueAt(const EcmaVM *vm, Local obj, uint32_t index, Local value); + static Local GetValueAt(const EcmaVM *vm, Local obj, uint32_t index); +}; + class ECMA_PUBLIC_API Int8ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index 1f00ca0956..94b0b68616 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -964,7 +964,7 @@ bool JSValueRef::IsSharedArray() bool JSValueRef::IsSharedTypedArray() { - return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedTypedArray(); + return JSNApiHelper::ToJSTaggedValue(this).IsSharedTypedArray(); } bool JSValueRef::IsSharedSet() @@ -1394,8 +1394,7 @@ Local BufferRef::New( CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); ObjectFactory *factory = vm->GetFactory(); - JSHandle arrayBuffer = - factory->NewJSArrayBuffer(buffer, length, reinterpret_cast(deleter), data); + JSHandle arrayBuffer = factory->NewJSArrayBuffer(buffer, length, deleter, data); JSHandle env = vm->GetGlobalEnv(); JSHandle current = @@ -2544,8 +2543,7 @@ Local ArrayBufferRef::New( CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); ObjectFactory *factory = vm->GetFactory(); - JSHandle arrayBuffer = - factory->NewJSArrayBuffer(buffer, length, reinterpret_cast(deleter), data); + JSHandle arrayBuffer = factory->NewJSArrayBuffer(buffer, length, deleter, data); return JSNApiHelper::ToLocal(JSHandle(arrayBuffer)); } @@ -2584,16 +2582,36 @@ bool ArrayBufferRef::IsDetach() return arrayBuffer->IsDetach(); } -Local ArrayBufferRef::NewSendable(const EcmaVM *vm, int32_t length) +Local SendableArrayBufferRef::New(const EcmaVM *vm, int32_t length) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); ObjectFactory *factory = vm->GetFactory(); JSHandle arrayBuffer = factory->NewJSSendableArrayBuffer(length); - return JSNApiHelper::ToLocal(JSHandle(arrayBuffer)); + return JSNApiHelper::ToLocal(JSHandle(arrayBuffer)); +} + +Local SendableArrayBufferRef::New( + const EcmaVM *vm, void *buffer, int32_t length, const NativePointerCallback &deleter, void *data) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); + ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); + ObjectFactory *factory = vm->GetFactory(); + JSHandle arrayBuffer = + factory->NewJSSendableArrayBuffer(buffer, length, deleter, data); + return JSNApiHelper::ToLocal(JSHandle(arrayBuffer)); +} + +int32_t SendableArrayBufferRef::ByteLength([[maybe_unused]] const EcmaVM *vm) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0); + ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); + JSHandle arrayBuffer(JSNApiHelper::ToJSHandle(this)); + LOG_IF_SPECIAL(arrayBuffer, FATAL); + return arrayBuffer->GetArrayBufferByteLength(); } -void ArrayBufferRef::SendableDetach(const EcmaVM *vm) +void SendableArrayBufferRef::Detach(const EcmaVM *vm) { CROSS_THREAD_AND_EXCEPTION_CHECK(vm); ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); @@ -2601,14 +2619,14 @@ void ArrayBufferRef::SendableDetach(const EcmaVM *vm) arrayBuffer->Detach(thread); } -bool ArrayBufferRef::SendableIsDetach() +bool SendableArrayBufferRef::IsDetach() { DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false); JSHandle arrayBuffer(JSNApiHelper::ToJSHandle(this)); return arrayBuffer->IsDetach(); } -void *ArrayBufferRef::SendableGetBuffer() +void *SendableArrayBufferRef::GetBuffer() { DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr); JSHandle arrayBuffer(JSNApiHelper::ToJSHandle(this)); @@ -2692,7 +2710,7 @@ Local TypedArrayRef::GetArrayBuffer(const EcmaVM *vm) return JSNApiHelper::ToLocal(arrayBuffer); } -uint32_t TypedArrayRef::SendableByteLength([[maybe_unused]] const EcmaVM *vm) +uint32_t SendableTypedArrayRef::ByteLength([[maybe_unused]] const EcmaVM *vm) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0); JSHandle typedArray(JSNApiHelper::ToJSHandle(this)); @@ -2700,7 +2718,7 @@ uint32_t TypedArrayRef::SendableByteLength([[maybe_unused]] const EcmaVM *vm) return typedArray->GetByteLength(); } -uint32_t TypedArrayRef::SendableByteOffset([[maybe_unused]] const EcmaVM *vm) +uint32_t SendableTypedArrayRef::ByteOffset([[maybe_unused]] const EcmaVM *vm) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0); JSHandle typedArray(JSNApiHelper::ToJSHandle(this)); @@ -2708,7 +2726,7 @@ uint32_t TypedArrayRef::SendableByteOffset([[maybe_unused]] const EcmaVM *vm) return typedArray->GetByteOffset(); } -uint32_t TypedArrayRef::SendableArrayLength([[maybe_unused]] const EcmaVM *vm) +uint32_t SendableTypedArrayRef::ArrayLength([[maybe_unused]] const EcmaVM *vm) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0); JSHandle typedArray(JSNApiHelper::ToJSHandle(this)); @@ -2716,14 +2734,15 @@ uint32_t TypedArrayRef::SendableArrayLength([[maybe_unused]] const EcmaVM *vm) return typedArray->GetArrayLength(); } -Local TypedArrayRef::SendableGetArrayBuffer(const EcmaVM *vm) +Local SendableTypedArrayRef::GetArrayBuffer(const EcmaVM *vm) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); ecmascript::ThreadManagedScope managedScope(thread); - JSHandle typeArray(JSNApiHelper::ToJSHandle(this)); + JSHandle typeArray(JSNApiHelper::ToJSHandle(this)); LOG_IF_SPECIAL(typeArray, ERROR); - JSHandle arrayBuffer(thread, JSTypedArray::GetSharedOffHeapBuffer(thread, typeArray)); - return JSNApiHelper::ToLocal(arrayBuffer); + JSHandle arrayBuffer(thread, + ecmascript::JSSharedTypedArray::GetSharedOffHeapBuffer(thread, typeArray)); + return JSNApiHelper::ToLocal(arrayBuffer); } // ----------------------------------- FunctionRef -------------------------------------- @@ -3212,6 +3231,41 @@ bool ArrayRef::SetValueAt(const EcmaVM *vm, Local obj, uint32_t inde return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle); } +// ----------------------------------- SendableArrayRef ---------------------------------------- +Local SendableArrayRef::New(const EcmaVM *vm, uint32_t length) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); + ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); + JSTaggedNumber arrayLen(length); + JSHandle array = ecmascript::JSSharedArray::ArrayCreate(thread, arrayLen); + RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); + return JSNApiHelper::ToLocal(array); +} + +uint32_t SendableArrayRef::Length([[maybe_unused]] const EcmaVM *vm) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0); + return ecmascript::JSSharedArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength(); +} + +Local SendableArrayRef::GetValueAt(const EcmaVM *vm, Local obj, uint32_t index) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); + ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); + JSHandle object = JSNApiHelper::ToJSHandle(obj); + JSHandle result = ecmascript::JSSharedArray::FastGetPropertyByValue(thread, object, index); + return JSNApiHelper::ToLocal(result); +} + +bool SendableArrayRef::SetValueAt(const EcmaVM *vm, Local obj, uint32_t index, Local value) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false); + ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); + JSHandle objectHandle = JSNApiHelper::ToJSHandle(obj); + JSHandle valueHandle = JSNApiHelper::ToJSHandle(value); + return ecmascript::JSSharedArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle); +} + // ---------------------------------- Error --------------------------------------- // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define EXCEPTION_ERROR_NEW(name, type) \ diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index efb5e215dd..7cc31731df 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -321,7 +321,27 @@ JSHandle ObjectFactory::NewJSSendableArrayBuffer(int32_t sendableArrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { NewJSSendableArrayBufferData(sendableArrayBuffer, length); - sendableArrayBuffer->SetShared(true); + sendableArrayBuffer->SetShared(false); + } + return sendableArrayBuffer; +} + +JSHandle ObjectFactory::NewJSSendableArrayBuffer(void *buffer, int32_t length, + const NativePointerCallback &deleter, + void *data) +{ + JSHandle env = vm_->GetGlobalEnv(); + + JSHandle constructor(env->GetSBuiltininArrayBufferFunction()); + JSHandle sendableArrayBuffer(NewJSObjectByConstructor(constructor)); + length = buffer == nullptr ? 0 : length; + sendableArrayBuffer->SetArrayBufferByteLength(length); + if (length > 0) { + JSHandle pointer = NewSJSNativePointer(buffer, deleter, data, false, length); + sendableArrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue()); + sendableArrayBuffer->SetShared(false); + sendableArrayBuffer->SetWithNativeAreaAllocator(deleter == NativeAreaAllocator::FreeBufferFunc && + data == vm_->GetNativeAreaAllocator()); } return sendableArrayBuffer; } diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index a929460781..000bd72bc4 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -490,6 +490,8 @@ public: void NewJSArrayBufferData(const JSHandle &array, int32_t length); void NewJSSendableArrayBufferData(const JSHandle &array, int32_t length); JSHandle NewJSSendableArrayBuffer(int32_t length); + JSHandle NewJSSendableArrayBuffer(void *buffer, int32_t length, + const NativePointerCallback &deleter, void *data); JSHandle NewJSArrayBuffer(int32_t length); diff --git a/ecmascript/shared_objects/js_shared_typed_array.h b/ecmascript/shared_objects/js_shared_typed_array.h index 8f63543aa5..f0f0ec9cc3 100755 --- a/ecmascript/shared_objects/js_shared_typed_array.h +++ b/ecmascript/shared_objects/js_shared_typed_array.h @@ -39,6 +39,8 @@ public: return static_cast(object); } + static JSTaggedValue GetSharedOffHeapBuffer(JSThread *thread, JSHandle typedArray); + static constexpr size_t MOD_RECORD_OFFSET = JSTypedArray::SIZE; ACCESSORS_SYNCHRONIZED_PRIMITIVE_FIELD(ModRecord, uint32_t, MOD_RECORD_OFFSET, LAST_OFFSET) DEFINE_ALIGN_SIZE(LAST_OFFSET); diff --git a/libark_jsruntime.map b/libark_jsruntime.map index 81dcd0cd73..3df7cabe19 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -17,8 +17,10 @@ panda::ecmascript::COMPILER_HELP_HEAD_MSG*; panda::ArrayBufferRef::*; + panda::SendableArrayBufferRef::*; panda::BufferRef::*; panda::ArrayRef::*; + panda::SendableArrayRef::*; panda::BigInt64ArrayRef::*; panda::BigIntRef::*; panda::BigUint64ArrayRef::*; @@ -50,6 +52,7 @@ panda::RegExpRef::*; panda::SetIteratorRef::*; panda::SetRef::*; + panda::SendableTypedArrayRef::*; panda::SharedInt8ArrayRef::*; panda::SharedUint8ArrayRef::*; panda::SharedInt16ArrayRef::*; diff --git a/test/test_helper.gni b/test/test_helper.gni index ced8c03bfd..0da4510f43 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -152,7 +152,7 @@ template("host_moduletest_action") { if (defined(invoker.is_merge_abc) && invoker.is_merge_abc) { _is_merge_abc_ = true } - _timeout_ = "200" + _timeout_ = "300" if (defined(invoker.timeout)) { _timeout_ = invoker.timeout } -- Gitee