• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/js_arguments.h"
17 
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/object_factory.h"
21 #include "ecmascript/tagged_array-inl.h"
22 
23 namespace panda::ecmascript {
GetOwnProperty(JSThread * thread,const JSHandle<JSArguments> & args,const JSHandle<JSTaggedValue> & key,PropertyDescriptor & desc)24 bool JSArguments::GetOwnProperty(JSThread *thread, const JSHandle<JSArguments> &args,
25                                  const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
26 {
27     // 1 ~ 3 Let desc be OrdinaryGetOwnProperty(args, P).
28     JSObject::OrdinaryGetOwnProperty(thread, JSHandle<JSObject>(args), key, desc);
29     if (desc.IsEmpty()) {
30         return true;
31     }
32 
33     // 4.Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
34     JSHandle<JSTaggedValue> map(thread, args->GetParameterMap());
35 
36     // 5.Let isMapped be HasOwnProperty(map, P).
37     bool isMapped = JSTaggedValue::HasOwnProperty(thread, map, key);
38 
39     // 6.Assert: isMapped is never an abrupt completion.
40     ASSERT(!thread->HasPendingException());
41 
42     // 7.If the value of isMapped is true, then
43     //   a.Set desc.[[Value]] to Get(map, P).
44     if (isMapped) {
45         auto prop = JSObject::GetProperty(thread, map, key).GetValue();
46         desc.SetValue(prop);
47     }
48 
49     // 8.If IsDataDescriptor(desc) is true and P is "caller" and desc.[[Value]] is a strict mode Function object,
50     //   throw a TypeError exception.
51     JSHandle<EcmaString> caller = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("caller");
52     if (desc.IsDataDescriptor() && JSTaggedValue::SameValue(key.GetTaggedValue(), caller.GetTaggedValue()) &&
53         desc.GetValue()->IsJSFunction()) {
54         THROW_TYPE_ERROR_AND_RETURN(thread, "Arguments GetOwnProperty: type error", false);
55     }
56     // 9.Return desc.
57     return true;
58 }
59 
DefineOwnProperty(JSThread * thread,const JSHandle<JSArguments> & args,const JSHandle<JSTaggedValue> & key,const PropertyDescriptor & desc)60 bool JSArguments::DefineOwnProperty(JSThread *thread, const JSHandle<JSArguments> &args,
61                                     const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc)
62 {
63     // 1 ~ 2 Let args be the arguments object and get map.
64     JSHandle<JSTaggedValue> map(thread, args->GetParameterMap());
65 
66     // 3.Let isMapped be HasOwnProperty(map, P).
67     bool isMapped = JSTaggedValue::HasOwnProperty(thread, map, key);
68 
69     // 4.Let allowed be OrdinaryDefineOwnProperty(args, P, Desc).
70     bool allowed = JSObject::OrdinaryDefineOwnProperty(thread, JSHandle<JSObject>(args), key, desc);
71 
72     // 5.ReturnIfAbrupt(allowed).
73     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, allowed);
74 
75     // 6.If allowed is false, return false.
76     if (!allowed) {
77         return false;
78     }
79 
80     // 7.If the value of isMapped is true, then
81     //   a.If IsAccessorDescriptor(Desc) is true, then
82     //     i.Call map.[[Delete]](P).
83     //   b.Else
84     //     i.If Desc.[[Value]] is present, then
85     //        1.Let setStatus be Set(map, P, Desc.[[Value]], false).
86     //        2.Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
87     //     ii.If Desc.[[Writable]] is present and its value is false, then
88     //        1.Call map.[[Delete]](P).
89     if (isMapped) {
90         if (desc.IsAccessorDescriptor()) {
91             JSTaggedValue::DeleteProperty(thread, map, key);
92         } else {
93             if (desc.HasValue()) {
94                 [[maybe_unused]] bool setStatus = JSTaggedValue::SetProperty(thread, map, key, desc.GetValue(), false);
95                 ASSERT(setStatus == true);
96             }
97             if (desc.HasWritable() && !desc.IsWritable()) {
98                 JSTaggedValue::DeleteProperty(thread, map, key);
99             }
100         }
101     }
102 
103     // 8.Return true.
104     return true;
105 }
106 
GetProperty(JSThread * thread,const JSHandle<JSArguments> & args,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & receiver)107 OperationResult JSArguments::GetProperty(JSThread *thread, const JSHandle<JSArguments> &args,
108                                          const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver)
109 {
110     // 1 ~ 2 Let args be the arguments object and get map.
111     JSHandle<JSTaggedValue> map(thread, args->GetParameterMap());
112 
113     // 3.Let isMapped be HasOwnProperty(map, P).
114     bool isMapped = JSTaggedValue::HasOwnProperty(thread, map, key);
115 
116     // 4.Assert: isMapped is not an abrupt completion.
117     ASSERT(!thread->HasPendingException());
118 
119     // 5.If the value of isMapped is false, then
120     //   a.Return the result of calling the default ordinary object [[Get]] internal method (9.1.8)
121     //   on args passing P and Receiver as the arguments.
122     if (!isMapped) {
123         return JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(args), key, receiver);
124     }
125 
126     // 6.Else map contains a formal parameter mapping for P,
127     //   a.Return Get(map, P).
128     return JSTaggedValue::GetProperty(thread, map, key);
129 }
130 
SetProperty(JSThread * thread,const JSHandle<JSArguments> & args,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value,const JSHandle<JSTaggedValue> & receiver)131 bool JSArguments::SetProperty(JSThread *thread, const JSHandle<JSArguments> &args, const JSHandle<JSTaggedValue> &key,
132                               const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &receiver)
133 {
134     // 1.Let args be the arguments object.
135     JSHandle<JSTaggedValue> map(thread, args->GetParameterMap());
136 
137     // 2.If SameValue(args, Receiver) is false, then
138     //   a.Let isMapped be false.
139     bool isMapped = false;
140     if (JSTaggedValue::SameValue(args.GetTaggedValue(), receiver.GetTaggedValue())) {
141         // 3.Else,
142         //   a.Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
143         //   b.Let isMapped be HasOwnProperty(map, P).
144         //   c.Assert: isMapped is not an abrupt completion.
145         isMapped = JSTaggedValue::HasOwnProperty(thread, map, key);
146         ASSERT(!thread->HasPendingException());
147     }
148 
149     // 4.If isMapped is true, then
150     //   a.Let setStatus be Set(map, P, V, false).
151     //   b.Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
152     if (isMapped) {
153         [[maybe_unused]] bool setStatus = JSTaggedValue::SetProperty(thread, map, key, value);
154         ASSERT(setStatus == true);
155     }
156 
157     // 5.Return the result of calling the default ordinary object [[Set]] internal method (9.1.9)
158     // on args passing P, V and Receiver as the arguments.
159     return JSTaggedValue::SetProperty(thread, JSHandle<JSTaggedValue>::Cast(args), key, value, receiver);
160 }
161 
DeleteProperty(JSThread * thread,const JSHandle<JSArguments> & args,const JSHandle<JSTaggedValue> & key)162 bool JSArguments::DeleteProperty(JSThread *thread, const JSHandle<JSArguments> &args,
163                                  const JSHandle<JSTaggedValue> &key)
164 {
165     // 1.Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
166     JSHandle<JSTaggedValue> map(thread, args->GetParameterMap());
167 
168     // 2.Let isMapped be HasOwnProperty(map, P).
169     bool isMapped = JSTaggedValue::HasOwnProperty(thread, map, key);
170 
171     // 3.Assert: isMapped is not an abrupt completion.
172     ASSERT(!thread->HasPendingException());
173 
174     // 4.Let result be the result of calling the default [[Delete]] internal method for ordinary objects (9.1.10)
175     // on the arguments object passing P as the argument.
176     bool result = JSTaggedValue::DeleteProperty(thread, JSHandle<JSTaggedValue>(args), key);
177 
178     // 5.ReturnIfAbrupt(result).
179     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, result);
180 
181     // 6.If result is true and the value of isMapped is true, then
182     //   a.Call map.[[Delete]](P).
183     if (result && isMapped) {
184         JSTaggedValue::DeleteProperty(thread, map, key);
185     }
186 
187     // 7.Return result.
188     return result;
189 }
190 }  // namespace panda::ecmascript
191