• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_function.h"
20 #include "ecmascript/napi/include/jsnapi_internals.h"
21 #include "ecmascript/napi/jsnapi_helper.h"
22 
23 namespace panda::ecmascript {
24 
JSNapiSendable(JSThread * thread,FunctionRef::SendablePropertiesInfos & infos,Local<StringRef> & name)25 JSNapiSendable::JSNapiSendable(JSThread *thread, FunctionRef::SendablePropertiesInfos &infos, Local<StringRef> &name)
26 {
27     InitStaticDescription(thread, staticDescs_, name);
28     InitNonStaticDescription(thread, nonStaticDescs_);
29     InitInstanceDescription(thread, instanceDescs_);
30     InitWithPropertiesInfo(thread, infos.staticPropertiesInfo, staticDescs_);
31     InitWithPropertiesInfo(thread, infos.nonStaticPropertiesInfo, nonStaticDescs_);
32     InitWithPropertiesInfo(thread, infos.instancePropertiesInfo, instanceDescs_);
33 }
34 
SetSConstructor(JSHandle<JSFunction> constructor)35 void JSNapiSendable::SetSConstructor(JSHandle<JSFunction> constructor)
36 {
37     nonStaticDescs_[0].SetValue(JSHandle<JSTaggedValue>::Cast(constructor));
38 }
39 
InitStaticDescription(JSThread * thread,std::vector<PropertyDescriptor> & descs,Local<StringRef> & name)40 void JSNapiSendable::InitStaticDescription(JSThread *thread,
41                                            std::vector<PropertyDescriptor> &descs,
42                                            Local<StringRef> &name)
43 {
44     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
45 
46     JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
47     PropertyDescriptor nameDesc(thread, false, false, false);
48     nameDesc.SetKey(nameKey);
49     nameDesc.SetSharedFieldType(SharedFieldType::STRING);
50     nameDesc.SetValue(JSNApiHelper::ToJSHandle(name));
51     descs.push_back(nameDesc);
52 
53     JSHandle<JSTaggedValue> prototypeKey = globalConst->GetHandledPrototypeString();
54     PropertyDescriptor prototypeDesc(thread, false, false, false);
55     prototypeDesc.SetKey(prototypeKey);
56     prototypeDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
57     prototypeDesc.SetValue(globalConst->GetHandledNull());
58     descs.push_back(prototypeDesc);
59 
60     JSHandle<JSTaggedValue> sendableElementsKey = globalConst->GetHandledSendableElementsSymbol();
61     PropertyDescriptor sendableElementsDesc(thread, false, false, false);
62     sendableElementsDesc.SetKey(sendableElementsKey);
63     sendableElementsDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
64     sendableElementsDesc.SetValue(globalConst->GetHandledUndefined());
65     descs.push_back(sendableElementsDesc);
66 }
67 
InitNonStaticDescription(JSThread * thread,std::vector<PropertyDescriptor> & descs)68 void JSNapiSendable::InitNonStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
69 {
70     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
71 
72     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
73     PropertyDescriptor constructorDesc(thread, false, false, false);
74     constructorDesc.SetKey(constructorKey);
75     constructorDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
76     constructorDesc.SetValue(globalConst->GetHandledNull());
77     descs.push_back(constructorDesc);
78 }
79 
InitInstanceDescription(JSThread * thread,std::vector<PropertyDescriptor> & descs)80 void JSNapiSendable::InitInstanceDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
81 {
82     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
83 
84     JSHandle<JSTaggedValue> napiWrapperKey = globalConst->GetHandledNapiWrapperString();
85     PropertyDescriptor napiWrapperDesc(thread, true, false, false);
86     napiWrapperDesc.SetKey(napiWrapperKey);
87     napiWrapperDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
88     napiWrapperDesc.SetValue(globalConst->GetHandledNull());
89     descs.push_back(napiWrapperDesc);
90 }
91 
InitWithPropertiesInfo(JSThread * thread,FunctionRef::SendablePropertiesInfo & info,std::vector<PropertyDescriptor> & descs)92 void JSNapiSendable::InitWithPropertiesInfo(JSThread *thread,
93                                             FunctionRef::SendablePropertiesInfo &info,
94                                             std::vector<PropertyDescriptor> &descs)
95 {
96     EcmaVM *vm = thread->GetEcmaVM();
97     auto length = info.keys.size();
98 
99     for (size_t i = 0; i < length; ++i) {
100         PropertyDescriptor desc(thread,
101                                 info.attributes[i].IsWritable(),
102                                 info.attributes[i].IsEnumerable(),
103                                 info.attributes[i].IsConfigurable());
104         desc.SetKey(JSNApiHelper::ToJSHandle(info.keys[i]));
105         auto type = GetSharedFieldType(thread, info.types[i], info.attributes[i].GetValue(vm));
106         desc.SetSharedFieldType(type);
107         desc.SetValue(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm)));
108         descs.push_back(desc);
109     }
110     InitInstanceDescription(thread, descs);
111 }
112 
GetSharedFieldType(JSThread * thread,FunctionRef::SendableType type,Local<JSValueRef> value)113 SharedFieldType JSNapiSendable::GetSharedFieldType(JSThread *thread,
114                                                    FunctionRef::SendableType type,
115                                                    Local<JSValueRef> value)
116 {
117     switch (type) {
118         case FunctionRef::SendableType::OBJECT:
119             return SharedFieldType::SENDABLE;
120         case FunctionRef::SendableType::GENERIC:
121             return SharedFieldType::GENERIC;
122         case FunctionRef::SendableType::NONE: {
123             auto valueHandle = JSNApiHelper::ToJSHandle(value);
124             if (valueHandle->IsUndefined()) {
125                 return SharedFieldType::NONE;
126             }
127             if (valueHandle->IsNull()) {
128                 // fixme: SharedFieldType::NULL ?
129                 return SharedFieldType::SENDABLE;
130             }
131             if (valueHandle->IsNumber()) {
132                 return SharedFieldType::NUMBER;
133             }
134             if (valueHandle->IsString()) {
135                 return SharedFieldType::STRING;
136             }
137             if (valueHandle->IsBoolean()) {
138                 return SharedFieldType::BOOLEAN;
139             }
140             if (valueHandle->IsJSShared()) {
141                 return SharedFieldType::SENDABLE;
142             }
143             if (valueHandle->IsBigInt()) {
144                 return SharedFieldType::BIG_INT;
145             }
146             THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
147         }
148         default:
149             THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
150     }
151 }
152 
153 }  // namespace panda::ecmascript
154