mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
!1454 Support transfer custom native object
Merge pull request !1454 from wangzhaoyong/master
This commit is contained in:
commit
267f0a20ac
@ -589,6 +589,10 @@ void Builtins::InitializeSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<J
|
||||
SetNoneAttributeProperty(symbolFunction, "toPrimitive", toPrimitiveSymbol);
|
||||
JSHandle<JSTaggedValue> unscopablesSymbol(factory_->NewPublicSymbolWithChar("Symbol.unscopables"));
|
||||
SetNoneAttributeProperty(symbolFunction, "unscopables", unscopablesSymbol);
|
||||
JSHandle<JSTaggedValue> attachSymbol(factory_->NewPublicSymbolWithChar("Symbol.attach"));
|
||||
SetNoneAttributeProperty(symbolFunction, "attach", attachSymbol);
|
||||
JSHandle<JSTaggedValue> detachSymbol(factory_->NewPublicSymbolWithChar("Symbol.detach"));
|
||||
SetNoneAttributeProperty(symbolFunction, "detach", detachSymbol);
|
||||
|
||||
// symbol.prototype.description
|
||||
PropertyDescriptor descriptionDesc(thread_);
|
||||
@ -618,6 +622,8 @@ void Builtins::InitializeSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<J
|
||||
env->SetSplitSymbol(thread_, splitSymbol);
|
||||
env->SetToPrimitiveSymbol(thread_, toPrimitiveSymbol);
|
||||
env->SetUnscopablesSymbol(thread_, unscopablesSymbol);
|
||||
env->SetAttachSymbol(thread_, attachSymbol);
|
||||
env->SetDetachSymbol(thread_, detachSymbol);
|
||||
|
||||
// Setup %SymbolPrototype%
|
||||
SetStringTagSymbol(env, symbolFuncPrototype, "Symbol");
|
||||
@ -673,6 +679,8 @@ void Builtins::InitializeSymbolWithRealm(const JSHandle<GlobalEnv> &realm,
|
||||
SetNoneAttributeProperty(symbolFunction, "split", env->GetSplitSymbol());
|
||||
SetNoneAttributeProperty(symbolFunction, "toPrimitive", env->GetToPrimitiveSymbol());
|
||||
SetNoneAttributeProperty(symbolFunction, "unscopables", env->GetUnscopablesSymbol());
|
||||
SetNoneAttributeProperty(symbolFunction, "attach", env->GetAttachSymbol());
|
||||
SetNoneAttributeProperty(symbolFunction, "detach", env->GetDetachSymbol());
|
||||
|
||||
// symbol.prototype.description
|
||||
PropertyDescriptor descriptionDesc(thread_);
|
||||
@ -703,6 +711,8 @@ void Builtins::InitializeSymbolWithRealm(const JSHandle<GlobalEnv> &realm,
|
||||
realm->SetSplitSymbol(thread_, env->GetSplitSymbol());
|
||||
realm->SetToPrimitiveSymbol(thread_, env->GetToPrimitiveSymbol());
|
||||
realm->SetUnscopablesSymbol(thread_, env->GetUnscopablesSymbol());
|
||||
realm->SetAttachSymbol(thread_, env->GetAttachSymbol());
|
||||
realm->SetDetachSymbol(thread_, env->GetDetachSymbol());
|
||||
|
||||
// Setup %SymbolPrototype%
|
||||
SetStringTagSymbol(realm, symbolFuncPrototype, "Symbol");
|
||||
|
@ -1967,6 +1967,10 @@ void GlobalEnv::Dump(std::ostream &os) const
|
||||
GetUnscopablesSymbol().GetTaggedValue().Dump(os);
|
||||
os << " - HoleySymbol: ";
|
||||
GetHoleySymbol().GetTaggedValue().Dump(os);
|
||||
os << " - AttachSymbol: ";
|
||||
GetAttachSymbol().GetTaggedValue().Dump(os);
|
||||
os << " - DetachSymbol: ";
|
||||
GetDetachSymbol().GetTaggedValue().Dump(os);
|
||||
os << " - ConstructorString: ";
|
||||
globalConst->GetConstructorString().Dump(os);
|
||||
os << " - IteratorPrototype: ";
|
||||
@ -3892,6 +3896,8 @@ void GlobalEnv::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &
|
||||
vec.push_back(std::make_pair(CString("ToPrimitiveSymbol"), GetToPrimitiveSymbol().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("UnscopablesSymbol"), GetUnscopablesSymbol().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("HoleySymbol"), GetHoleySymbol().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("AttachSymbol"), GetAttachSymbol().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("DetachSymbol"), GetDetachSymbol().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("ConstructorString"), globalConst->GetConstructorString()));
|
||||
vec.push_back(std::make_pair(CString("IteratorPrototype"), GetIteratorPrototype().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("ForinIteratorPrototype"), GetForinIteratorPrototype().GetTaggedValue()));
|
||||
|
@ -150,7 +150,9 @@ class JSThread;
|
||||
V(JSTaggedValue, ModuleNamespaceClass, MODULENAMESPACE_CLASS) \
|
||||
V(JSTaggedValue, ObjectLiteralHClassCache, OBJECT_LITERAL_HCLASS_CACHE) \
|
||||
V(JSTaggedValue, WeakRefKeepObjects, WEAK_REF_KEEP_OBJECTS) \
|
||||
V(JSTaggedValue, FinRegLists, FIN_REG_LISTS)
|
||||
V(JSTaggedValue, FinRegLists, FIN_REG_LISTS) \
|
||||
V(JSTaggedValue, AttachSymbol, ATTACH_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, DetachSymbol, DETACH_SYMBOL_INDEX)
|
||||
|
||||
class GlobalEnv : public TaggedObject {
|
||||
public:
|
||||
|
@ -664,6 +664,16 @@ bool JSSerializer::WritePlainObject(const JSHandle<JSTaggedValue> &objValue)
|
||||
{
|
||||
JSHandle<JSObject> obj = JSHandle<JSObject>::Cast(objValue);
|
||||
size_t oldSize = bufferSize_;
|
||||
std::vector<JSTaggedValue> keyVector;
|
||||
uint32_t propertiesLength = obj->GetNumberOfKeys();
|
||||
JSObject::GetAllKeys(thread_, obj, keyVector);
|
||||
if (keyVector.size() != propertiesLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyVector.size() >= 2 && (keyVector[0].IsSymbol() && keyVector[1].IsSymbol())) { // 2:attachSymbol, detachSymbol
|
||||
return WriteNativeObject(objValue, keyVector);
|
||||
}
|
||||
if (!WriteType(SerializationUID::JS_PLAIN_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
@ -673,7 +683,7 @@ bool JSSerializer::WritePlainObject(const JSHandle<JSTaggedValue> &objValue)
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
std::vector<JSTaggedValue> keyVector;
|
||||
keyVector.clear();
|
||||
JSObject::GetALLElementKeysIntoVector(thread_, obj, keyVector);
|
||||
// Write elements' description attributes and value
|
||||
if (keyVector.size() != elementsLength) {
|
||||
@ -700,7 +710,6 @@ bool JSSerializer::WritePlainObject(const JSHandle<JSTaggedValue> &objValue)
|
||||
}
|
||||
// Get the number of k-v form properties stored in obj
|
||||
keyVector.clear();
|
||||
uint32_t propertiesLength = obj->GetNumberOfKeys();
|
||||
if (!WriteInt(static_cast<int32_t>(propertiesLength))) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
@ -736,6 +745,65 @@ bool JSSerializer::WritePlainObject(const JSHandle<JSTaggedValue> &objValue)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSSerializer::WriteNativeObject(const JSHandle<JSTaggedValue> &objValue, std::vector<JSTaggedValue> keyVector)
|
||||
{
|
||||
JSHandle<JSObject> obj = JSHandle<JSObject>::Cast(objValue);
|
||||
size_t oldSize = bufferSize_;
|
||||
JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> detach = env->GetDetachSymbol();
|
||||
JSHandle<JSTaggedValue> attach = env->GetAttachSymbol();
|
||||
if (!(JSTaggedValue::Equal(thread_, detach, JSHandle<JSTaggedValue>(thread_, keyVector[0]))) ||
|
||||
!(JSTaggedValue::Equal(thread_, attach, JSHandle<JSTaggedValue>(thread_, keyVector[1])))) {
|
||||
return false;
|
||||
}
|
||||
if (!WriteType(SerializationUID::JS_NATIVE_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
// Write custom object's values: AttachFunc*, buffer*
|
||||
JSHandle<JSTaggedValue> detachVal = JSObject::GetProperty(thread_, obj, detach).GetRawValue();
|
||||
JSHandle<JSTaggedValue> attackVal = JSObject::GetProperty(thread_, obj, attach).GetRawValue();
|
||||
DetachFunc detachNative = reinterpret_cast<DetachFunc>(JSNativePointer::Cast(
|
||||
detachVal.GetTaggedValue().GetTaggedObject())->GetExternalPointer());
|
||||
void *buffer = detachNative();
|
||||
AttachFunc attachNative = reinterpret_cast<AttachFunc>(JSNativePointer::Cast(
|
||||
attackVal.GetTaggedValue().GetTaggedObject())->GetExternalPointer());
|
||||
if (!WriteRawData(&attachNative, sizeof(uintptr_t))) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
if (!WriteRawData(&buffer, sizeof(uintptr_t))) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
if (keyVector.size() > 2) { // 2:attachSymbol, detachSymbol
|
||||
uint32_t propertiesLength = keyVector.size() - 2;
|
||||
if (!WriteInt(static_cast<int32_t>(propertiesLength))) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
// Write keys' description attributes and related values
|
||||
for (uint32_t i = 0; i < propertiesLength; i++) {
|
||||
JSMutableHandle<JSTaggedValue> key(thread_, keyVector[i + 2]); // 2:attachSymbol, detachSymbol
|
||||
if (!SerializeJSTaggedValue(key)) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
PropertyDescriptor desc(thread_);
|
||||
JSObject::OrdinaryGetOwnProperty(thread_, obj, key, desc);
|
||||
if (!WriteDesc(desc)) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
JSHandle<JSTaggedValue> value = desc.GetValue();
|
||||
if (!SerializeJSTaggedValue(value)) {
|
||||
bufferSize_ = oldSize;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSSerializer::WriteDesc(const PropertyDescriptor &desc)
|
||||
{
|
||||
size_t oldSize = bufferSize_;
|
||||
@ -874,6 +942,8 @@ JSHandle<JSTaggedValue> JSDeserializer::DeserializeJSTaggedValue()
|
||||
return ReadJSDate();
|
||||
case SerializationUID::JS_PLAIN_OBJECT:
|
||||
return ReadPlainObject();
|
||||
case SerializationUID::JS_NATIVE_OBJECT:
|
||||
return ReadNativeObject();
|
||||
case SerializationUID::JS_ARRAY:
|
||||
return ReadJSArray();
|
||||
case SerializationUID::ECMASTRING:
|
||||
@ -1045,6 +1115,52 @@ JSHandle<JSTaggedValue> JSDeserializer::ReadPlainObject()
|
||||
return objTag;
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> JSDeserializer::ReadNativeObject()
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> objFunc = env->GetObjectFunction();
|
||||
JSHandle<JSObject> jsObject =
|
||||
thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
|
||||
JSHandle<JSTaggedValue> objTag(jsObject);
|
||||
referenceMap_.insert(std::pair(objectId_++, objTag));
|
||||
|
||||
JSTaggedValue pointer;
|
||||
if (!ReadJSTaggedValue(&pointer)) {
|
||||
return JSHandle<JSTaggedValue>();
|
||||
}
|
||||
AttachFunc attachFunc = reinterpret_cast<AttachFunc>(JSNativePointer::Cast(pointer.GetTaggedObject()));
|
||||
JSTaggedValue bufferPointer;
|
||||
if (!ReadJSTaggedValue(&bufferPointer)) {
|
||||
return JSHandle<JSTaggedValue>();
|
||||
}
|
||||
void *buffer = reinterpret_cast<void *>(JSNativePointer::Cast(bufferPointer.GetTaggedObject()));
|
||||
attachFunc(buffer);
|
||||
|
||||
int32_t propertyLength;
|
||||
if (!JudgeType(SerializationUID::INT32) || !ReadInt(&propertyLength)) {
|
||||
return objTag;
|
||||
}
|
||||
for (int32_t i = 0; i < propertyLength; i++) {
|
||||
JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue();
|
||||
if (key.IsEmpty()) {
|
||||
return JSHandle<JSTaggedValue>();
|
||||
}
|
||||
PropertyDescriptor desc(thread_);
|
||||
if (!ReadDesc(&desc)) {
|
||||
return JSHandle<JSTaggedValue>();
|
||||
}
|
||||
JSHandle<JSTaggedValue> value = DeserializeJSTaggedValue();
|
||||
if (value.IsEmpty()) {
|
||||
return JSHandle<JSTaggedValue>();
|
||||
}
|
||||
desc.SetValue(value);
|
||||
if (!JSTaggedValue::DefineOwnProperty(thread_, objTag, key, desc)) {
|
||||
return JSHandle<JSTaggedValue>();
|
||||
}
|
||||
}
|
||||
return objTag;
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> JSDeserializer::ReadJSMap()
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
|
||||
|
@ -28,6 +28,9 @@
|
||||
#include "ecmascript/mem/dyn_chunk.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
typedef void* (*DetachFunc)(void);
|
||||
typedef void (*AttachFunc)(void* buffer);
|
||||
|
||||
enum class SerializationUID : uint8_t {
|
||||
// JS special values
|
||||
JS_NULL = 0x01,
|
||||
@ -50,6 +53,7 @@ enum class SerializationUID : uint8_t {
|
||||
JS_DATE,
|
||||
JS_REG_EXP,
|
||||
JS_PLAIN_OBJECT,
|
||||
JS_NATIVE_OBJECT,
|
||||
JS_SET,
|
||||
JS_MAP,
|
||||
JS_ARRAY,
|
||||
@ -113,6 +117,7 @@ private:
|
||||
bool WriteEcmaString(const JSHandle<JSTaggedValue> &value);
|
||||
bool WriteJSTypedArray(const JSHandle<JSTaggedValue> &value, SerializationUID uId);
|
||||
bool WritePlainObject(const JSHandle<JSTaggedValue> &value);
|
||||
bool WriteNativeObject(const JSHandle<JSTaggedValue> &value, std::vector<JSTaggedValue> keyVector);
|
||||
bool WriteNativeFunctionPointer(const JSHandle<JSTaggedValue> &value);
|
||||
bool WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value);
|
||||
bool WriteDesc(const PropertyDescriptor &desc);
|
||||
@ -160,6 +165,7 @@ private:
|
||||
JSHandle<JSTaggedValue> ReadNativeFunctionPointer();
|
||||
JSHandle<JSTaggedValue> ReadJSArrayBuffer();
|
||||
JSHandle<JSTaggedValue> ReadReference();
|
||||
JSHandle<JSTaggedValue> ReadNativeObject();
|
||||
bool JudgeType(SerializationUID targetUid);
|
||||
void *GetBuffer(uint32_t bufferSize);
|
||||
bool ReadJSTaggedValue(JSTaggedValue *originalFlags);
|
||||
|
@ -72,12 +72,10 @@ void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedA
|
||||
void LayoutInfo::GetAllKeys([[maybe_unused]] const JSThread *thread, int end, std::vector<JSTaggedValue> &keyVector)
|
||||
{
|
||||
ASSERT(end <= NumberOfElements());
|
||||
int enumKeys = 0;
|
||||
for (int i = 0; i < end; i++) {
|
||||
JSTaggedValue key = GetKey(i);
|
||||
if (key.IsString()) {
|
||||
if (key.IsString() || key.IsSymbol()) {
|
||||
keyVector.emplace_back(key);
|
||||
enumKeys++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -669,6 +669,7 @@ public:
|
||||
return static_cast<ObjectRef *>(value);
|
||||
}
|
||||
static Local<ObjectRef> New(const EcmaVM *vm);
|
||||
static Local<ObjectRef> New(const EcmaVM *vm, void *attach, void *detach);
|
||||
bool Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value);
|
||||
bool Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value);
|
||||
bool SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
|
||||
|
@ -741,6 +741,23 @@ Local<ObjectRef> ObjectRef::New(const EcmaVM *vm)
|
||||
return JSNApiHelper::ToLocal<ObjectRef>(object);
|
||||
}
|
||||
|
||||
Local<ObjectRef> ObjectRef::New(const EcmaVM *vm, void *detach, void *attach)
|
||||
{
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> constructor = env->GetObjectFunction();
|
||||
JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
|
||||
JSHandle<JSTaggedValue> detachKey = env->GetDetachSymbol();
|
||||
JSHandle<JSTaggedValue> attachKey = env->GetAttachSymbol();
|
||||
JSHandle<JSTaggedValue> detachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, detach));
|
||||
JSHandle<JSTaggedValue> attachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, attach));
|
||||
JSTaggedValue::SetProperty(vm->GetJSThread(), object, detachKey, detachValue);
|
||||
RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Exception(vm));
|
||||
JSTaggedValue::SetProperty(vm->GetJSThread(), object, attachKey, attachValue);
|
||||
RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Exception(vm));
|
||||
return JSNApiHelper::ToLocal<ObjectRef>(object);
|
||||
}
|
||||
|
||||
bool ObjectRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
|
||||
{
|
||||
[[maybe_unused]] LocalScope scope(vm);
|
||||
|
Loading…
Reference in New Issue
Block a user