• 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 #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     JSHandle<JSTaggedValue> sendableElementsKey = globalConst->GetHandledSendableElementsSymbol();
59     PropertyDescriptor sendableElementsDesc(thread, false, false, false);
60     sendableElementsDesc.SetKey(sendableElementsKey);
61     sendableElementsDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
62     sendableElementsDesc.SetValue(globalConst->GetHandledUndefined());
63     descs.push_back(sendableElementsDesc);
64 }
65 
InitNonStaticDescription(JSThread * thread,std::vector<PropertyDescriptor> & descs)66 void JSNapiSendable::InitNonStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
67 {
68     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
69 
70     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
71     PropertyDescriptor constructorDesc(thread, false, false, false);
72     constructorDesc.SetKey(constructorKey);
73     constructorDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
74     constructorDesc.SetValue(globalConst->GetHandledNull());
75     descs.push_back(constructorDesc);
76 }
77 
InitInstanceDescription(JSThread * thread,std::vector<PropertyDescriptor> & descs)78 void JSNapiSendable::InitInstanceDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
79 {
80     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
81 
82     JSHandle<JSTaggedValue> napiWrapperKey = globalConst->GetHandledNapiWrapperString();
83     PropertyDescriptor napiWrapperDesc(thread, true, false, false);
84     napiWrapperDesc.SetKey(napiWrapperKey);
85     napiWrapperDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
86     napiWrapperDesc.SetValue(globalConst->GetHandledNull());
87     descs.push_back(napiWrapperDesc);
88 }
89 
InitWithPropertiesInfo(JSThread * thread,FunctionRef::SendablePropertiesInfo & info,std::vector<PropertyDescriptor> & descs)90 void JSNapiSendable::InitWithPropertiesInfo(JSThread *thread,
91                                             FunctionRef::SendablePropertiesInfo &info,
92                                             std::vector<PropertyDescriptor> &descs)
93 {
94     EcmaVM *vm = thread->GetEcmaVM();
95     auto length = info.keys.size();
96 
97     for (size_t i = 0; i < length; ++i) {
98         PropertyDescriptor desc(thread,
99                                 info.attributes[i].IsWritable(),
100                                 info.attributes[i].IsEnumerable(),
101                                 info.attributes[i].IsConfigurable());
102         desc.SetKey(JSNApiHelper::ToJSHandle(info.keys[i]));
103         auto type = GetSharedFieldType(thread, info.types[i], info.attributes[i].GetValue(vm));
104         desc.SetSharedFieldType(type);
105         desc.SetValue(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm)));
106         descs.push_back(desc);
107     }
108     InitInstanceDescription(thread, descs);
109 }
110 
GetSharedFieldType(JSThread * thread,FunctionRef::SendableType type,Local<JSValueRef> value)111 SharedFieldType JSNapiSendable::GetSharedFieldType(JSThread *thread,
112                                                    FunctionRef::SendableType type,
113                                                    Local<JSValueRef> value)
114 {
115     switch (type) {
116         case FunctionRef::SendableType::OBJECT:
117             return SharedFieldType::SENDABLE;
118         case FunctionRef::SendableType::GENERIC:
119             return SharedFieldType::GENERIC;
120         case FunctionRef::SendableType::NONE: {
121             auto valueHandle = JSNApiHelper::ToJSHandle(value);
122             if (valueHandle->IsUndefined()) {
123                 return SharedFieldType::NONE;
124             }
125             if (valueHandle->IsNull()) {
126                 // fixme: SharedFieldType::NULL ?
127                 return SharedFieldType::SENDABLE;
128             }
129             if (valueHandle->IsNumber()) {
130                 return SharedFieldType::NUMBER;
131             }
132             if (valueHandle->IsString()) {
133                 return SharedFieldType::STRING;
134             }
135             if (valueHandle->IsBoolean()) {
136                 return SharedFieldType::BOOLEAN;
137             }
138             if (valueHandle->IsJSShared()) {
139                 return SharedFieldType::SENDABLE;
140             }
141             if (valueHandle->IsBigInt()) {
142                 return SharedFieldType::BIG_INT;
143             }
144             THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
145         }
146         default:
147             THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
148     }
149 }
150 
151 }  // namespace panda::ecmascript
152