1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/jsnapi_sendable.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/napi/jsnapi_helper.h"
19 #include "js_function.h"
20
21 namespace panda::ecmascript {
22
JSNapiSendable(JSThread *thread, FunctionRef::SendablePropertiesInfos &infos, Local<StringRef> &name)23 JSNapiSendable::JSNapiSendable(JSThread *thread, FunctionRef::SendablePropertiesInfos &infos, Local<StringRef> &name)
24 {
25 InitStaticDescription(thread, staticDescs_, name);
26 InitNonStaticDescription(thread, nonStaticDescs_);
27 InitInstanceDescription(thread, instanceDescs_);
28 InitWithPropertiesInfo(thread, infos.staticPropertiesInfo, staticDescs_);
29 InitWithPropertiesInfo(thread, infos.nonStaticPropertiesInfo, nonStaticDescs_);
30 InitWithPropertiesInfo(thread, infos.instancePropertiesInfo, instanceDescs_);
31 }
32
SetSConstructor(JSHandle<JSFunction> constructor)33 void JSNapiSendable::SetSConstructor(JSHandle<JSFunction> constructor)
34 {
35 nonStaticDescs_[0].SetValue(JSHandle<JSTaggedValue>::Cast(constructor));
36 }
37
InitStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs, Local<StringRef> &name)38 void JSNapiSendable::InitStaticDescription(JSThread *thread,
39 std::vector<PropertyDescriptor> &descs,
40 Local<StringRef> &name)
41 {
42 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
43
44 JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
45 PropertyDescriptor nameDesc(thread, false, false, false);
46 nameDesc.SetKey(nameKey);
47 nameDesc.SetSharedFieldType(SharedFieldType::STRING);
48 nameDesc.SetValue(JSNApiHelper::ToJSHandle(name));
49 descs.push_back(nameDesc);
50
51 JSHandle<JSTaggedValue> prototypeKey = globalConst->GetHandledPrototypeString();
52 PropertyDescriptor prototypeDesc(thread, false, false, false);
53 prototypeDesc.SetKey(prototypeKey);
54 prototypeDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
55 prototypeDesc.SetValue(globalConst->GetHandledNull());
56 descs.push_back(prototypeDesc);
57 }
58
InitNonStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)59 void JSNapiSendable::InitNonStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
60 {
61 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
62
63 JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
64 PropertyDescriptor constructorDesc(thread, false, false, false);
65 constructorDesc.SetKey(constructorKey);
66 constructorDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
67 constructorDesc.SetValue(globalConst->GetHandledNull());
68 descs.push_back(constructorDesc);
69 }
70
InitInstanceDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)71 void JSNapiSendable::InitInstanceDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
72 {
73 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
74
75 JSHandle<JSTaggedValue> napiWrapperKey = globalConst->GetHandledNapiWrapperString();
76 PropertyDescriptor napiWrapperDesc(thread, true, false, false);
77 napiWrapperDesc.SetKey(napiWrapperKey);
78 napiWrapperDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
79 napiWrapperDesc.SetValue(globalConst->GetHandledNull());
80 descs.push_back(napiWrapperDesc);
81 }
82
InitWithPropertiesInfo(JSThread *thread, FunctionRef::SendablePropertiesInfo &info, std::vector<PropertyDescriptor> &descs)83 void JSNapiSendable::InitWithPropertiesInfo(JSThread *thread,
84 FunctionRef::SendablePropertiesInfo &info,
85 std::vector<PropertyDescriptor> &descs)
86 {
87 EcmaVM *vm = thread->GetEcmaVM();
88 auto length = info.keys.size();
89
90 for (size_t i = 0; i < length; ++i) {
91 PropertyDescriptor desc(thread,
92 info.attributes[i].IsWritable(),
93 info.attributes[i].IsEnumerable(),
94 info.attributes[i].IsConfigurable());
95 desc.SetKey(JSNApiHelper::ToJSHandle(info.keys[i]));
96 auto type = GetSharedFieldType(thread, info.types[i], info.attributes[i].GetValue(vm));
97 desc.SetSharedFieldType(type);
98 desc.SetValue(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm)));
99 descs.push_back(desc);
100 }
101 InitInstanceDescription(thread, descs);
102 }
103
GetSharedFieldType(JSThread *thread, FunctionRef::SendableType type, Local<JSValueRef> value)104 SharedFieldType JSNapiSendable::GetSharedFieldType(JSThread *thread,
105 FunctionRef::SendableType type,
106 Local<JSValueRef> value)
107 {
108 switch (type) {
109 case FunctionRef::SendableType::OBJECT:
110 return SharedFieldType::SENDABLE;
111 case FunctionRef::SendableType::GENERIC:
112 return SharedFieldType::GENERIC;
113 case FunctionRef::SendableType::NONE: {
114 auto valueHandle = JSNApiHelper::ToJSHandle(value);
115 if (valueHandle->IsUndefined()) {
116 return SharedFieldType::NONE;
117 }
118 if (valueHandle->IsNull()) {
119 // fixme: SharedFieldType::NULL ?
120 return SharedFieldType::SENDABLE;
121 }
122 if (valueHandle->IsNumber()) {
123 return SharedFieldType::NUMBER;
124 }
125 if (valueHandle->IsString()) {
126 return SharedFieldType::STRING;
127 }
128 if (valueHandle->IsBoolean()) {
129 return SharedFieldType::BOOLEAN;
130 }
131 if (valueHandle->IsJSShared()) {
132 return SharedFieldType::SENDABLE;
133 }
134 if (valueHandle->IsBigInt()) {
135 return SharedFieldType::BIG_INT;
136 }
137 THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
138 }
139 default:
140 THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
141 }
142 }
143
144 } // namespace panda::ecmascript
145