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 "ark_interop_napi.h"
17 #include "ark_interop_internal.h"
18 #include "ark_interop_log.h"
19 
20 using namespace panda;
21 using namespace panda::ecmascript;
22 
ARKTSInner_IsJSKey(ARKTS_Env env, ARKTS_Value value)23 ARKTS_INLINE bool ARKTSInner_IsJSKey(ARKTS_Env env, ARKTS_Value value)
24 {
25     auto tag = BIT_CAST(value, JSValueRef);
26     if (!tag.IsHeapObject()) {
27         return false;
28     }
29     tag = *P_CAST(value, JSValueRef*);
30     auto vm = P_CAST(env, EcmaVM*);
31     return tag.IsString(vm) || tag.IsSymbol(vm);
32 }
33 
ARKTS_CreateObject(ARKTS_Env env)34 ARKTS_Value ARKTS_CreateObject(ARKTS_Env env)
35 {
36     ARKTS_ASSERT_P(env, "env is null");
37 
38     auto vm = P_CAST(env, EcmaVM*);
39     auto result = ObjectRef::New(vm);
40 
41     return BIT_CAST(result, ARKTS_Value);
42 }
43 
ARKTS_IsHeapObject(ARKTS_Value value)44 bool ARKTS_IsHeapObject(ARKTS_Value value)
45 {
46     auto v = BIT_CAST(value, JSValueRef);
47     return v.IsHeapObject();
48 }
49 
ARKTS_IsObject(ARKTS_Env env, ARKTS_Value value)50 bool ARKTS_IsObject(ARKTS_Env env, ARKTS_Value value)
51 {
52     auto v = BIT_CAST(value, JSValueRef);
53     if (!v.IsHeapObject()) {
54         return false;
55     }
56     v = *P_CAST(value, JSValueRef*);
57     auto vm = P_CAST(env, EcmaVM*);
58     return v.IsObject(vm);
59 }
60 
ARKTS_HasOwnProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey)61 bool ARKTS_HasOwnProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey)
62 {
63     ARKTS_ASSERT_F(env, "env is null");
64     ARKTS_ASSERT_F(ARKTS_IsHeapObject(jobj), "object is not heap object");
65     ARKTS_ASSERT_F(ARKTSInner_IsJSKey(env, jkey), "key is not string or symbol");
66 
67     auto vm = P_CAST(env, EcmaVM*);
68     auto object = BIT_CAST(jobj, Local<ObjectRef>);
69     auto key = BIT_CAST(jkey, Local<JSValueRef>);
70     return object->Has(vm, key);
71 }
72 
ARKTS_EnumOwnProperties(ARKTS_Env env, ARKTS_Value jobj)73 ARKTS_Value ARKTS_EnumOwnProperties(ARKTS_Env env, ARKTS_Value jobj)
74 {
75     ARKTS_ASSERT_P(env, "env is null");
76     ARKTS_ASSERT_P(ARKTS_IsHeapObject(jobj), "object is not heap object");
77 
78     auto vm = P_CAST(env, EcmaVM*);
79     auto object = BIT_CAST(jobj, Local<ObjectRef>);
80     auto result = object->GetOwnEnumerablePropertyNames(vm);
81 
82     return BIT_CAST(result, ARKTS_Value);
83 }
84 
ARKTS_DefineOwnProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey, ARKTS_Value jvalue, ARKTS_PropertyFlag attrs)85 void ARKTS_DefineOwnProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey, ARKTS_Value jvalue,
86     ARKTS_PropertyFlag attrs)
87 {
88     ARKTS_ASSERT_V(env, "env is null");
89     ARKTS_ASSERT_V(ARKTS_IsHeapObject(jobj), "object is not heap object");
90     ARKTS_ASSERT_V(ARKTSInner_IsJSKey(env, jkey), "key is not string or symbol");
91 
92     auto vm = P_CAST(env, EcmaVM*);
93     auto object = BIT_CAST(jobj, Local<ObjectRef>);
94     auto key = BIT_CAST(jkey, Local<JSValueRef>);
95     auto value = ARKTS_ToHandle<JSValueRef>(jvalue);
96 
97     PropertyAttribute attribute(value, attrs & N_WRITABLE, attrs & N_ENUMERABLE, attrs & N_CONFIGURABLE);
98     object->DefineProperty(vm, key, attribute);
99 }
100 
ARKTS_DefineAccessors(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey, ARKTS_Accessor accessor)101 void ARKTS_DefineAccessors(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey, ARKTS_Accessor accessor)
102 {
103     ARKTS_ASSERT_V(env, "env is null");
104     ARKTS_ASSERT_V(ARKTS_IsHeapObject(jobj), "object is not heap object");
105     ARKTS_ASSERT_V(ARKTSInner_IsJSKey(env, jkey), "key is not string or symbol");
106 
107     auto undefined = ARKTS_CreateUndefined();
108 
109     ARKTS_ASSERT_V(accessor.setter == undefined || ARKTS_IsCallable(env, accessor.setter), "setter not callable");
110     ARKTS_ASSERT_V(accessor.getter == undefined || ARKTS_IsCallable(env, accessor.getter), "getter not callable");
111     ARKTS_ASSERT_V(accessor.getter != undefined || accessor.setter != undefined, "getter and setter is undefined");
112 
113     auto vm = P_CAST(env, EcmaVM*);
114     auto object = BIT_CAST(jobj, Local<ObjectRef>);
115     auto key = BIT_CAST(jkey, Local<JSValueRef>);
116     auto handledUndef = ARKTS_ToHandle<JSValueRef>(undefined);
117     auto handledGetter = accessor.getter != undefined ? BIT_CAST(accessor.getter, Local<JSValueRef>) : handledUndef;
118     auto handledSetter = accessor.setter != undefined ? BIT_CAST(accessor.setter, Local<JSValueRef>) : handledUndef;
119 
120     PropertyAttribute attribute(handledUndef,
121         accessor.attrs & N_WRITABLE,
122         accessor.attrs & N_ENUMERABLE,
123         accessor.attrs & N_CONFIGURABLE);
124     object->SetAccessorProperty(vm, key, handledGetter, handledSetter, attribute);
125 }
126 
ARKTS_SetProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey, ARKTS_Value jvalue)127 void ARKTS_SetProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey, ARKTS_Value jvalue)
128 {
129     ARKTS_ASSERT_V(env, "env is null");
130     ARKTS_ASSERT_V(ARKTS_IsHeapObject(jobj), "object is not heap object");
131     ARKTS_ASSERT_V(ARKTSInner_IsJSKey(env, jkey), "key is not string or symbol");
132 
133     auto vm = P_CAST(env, EcmaVM*);
134     auto object = BIT_CAST(jobj, Local<ObjectRef>);
135     auto key = BIT_CAST(jkey, Local<JSValueRef>);
136     auto value = ARKTS_ToHandle<JSValueRef>(jvalue);
137 
138     object->Set(vm, key, value);
139 }
140 
ARKTS_GetProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey)141 ARKTS_Value ARKTS_GetProperty(ARKTS_Env env, ARKTS_Value jobj, ARKTS_Value jkey)
142 {
143     ARKTS_ASSERT_P(env, "env is null");
144     ARKTS_ASSERT_P(ARKTS_IsHeapObject(jobj), "object is not heap object");
145     ARKTS_ASSERT_P(ARKTSInner_IsJSKey(env, jkey), "key is not string or symbol");
146 
147     auto vm = P_CAST(env, EcmaVM*);
148     auto object = BIT_CAST(jobj, Local<ObjectRef>);
149     auto key = BIT_CAST(jkey, Local<JSValueRef>);
150 
151     auto result = object->Get(vm, key);
152     return ARKTS_FromHandle(result);
153 }
154