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/builtins/builtins_object.h"
17 
18 #include "ecmascript/builtins/builtins_map.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_primitive_ref.h"
21 #include "ecmascript/object_fast_operator-inl.h"
22 
23 namespace panda::ecmascript::builtins {
24 // 19.1.1.1 Object ( [ value ] )
ObjectConstructor(EcmaRuntimeCallInfo *argv)25 JSTaggedValue BuiltinsObject::ObjectConstructor(EcmaRuntimeCallInfo *argv)
26 {
27     ASSERT(argv);
28     JSThread *thread = argv->GetThread();
29     BUILTINS_API_TRACE(thread, Object, Constructor);
30     [[maybe_unused]] EcmaHandleScope handleScope(thread);
31     auto ecmaVm = thread->GetEcmaVM();
32     JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
33 
34     // 1.If NewTarget is neither undefined nor the active function, then
35     //    a.Return OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
36     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
37     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
38     if (!newTarget->IsUndefined() && !(newTarget.GetTaggedValue() == constructor.GetTaggedValue())) {
39         JSHandle<JSObject> obj =
40             ecmaVm->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
41         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
42         return obj.GetTaggedValue();
43     }
44 
45     // 2.If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%).
46     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
47     if (value->IsNull() || value->IsUndefined()) {
48         JSHandle<JSObject> obj = ecmaVm->GetFactory()->OrdinaryNewJSObjectCreate(env->GetObjectFunctionPrototype());
49         return obj.GetTaggedValue();
50     }
51 
52     // 3.Return ToObject(value).
53     return JSTaggedValue::ToObject(thread, value).GetTaggedValue();
54 }
55 
AssignTaggedValue(JSThread *thread, const JSHandle<JSTaggedValue> &source, const JSHandle<JSObject> &toAssign)56 JSTaggedValue BuiltinsObject::AssignTaggedValue(JSThread *thread, const JSHandle<JSTaggedValue> &source,
57                                                 const JSHandle<JSObject> &toAssign)
58 {
59     JSHandle<JSObject> from = JSTaggedValue::ToObject(thread, source);
60     JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(from));
61     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
62 
63     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
64     uint32_t keysLen = keys->GetLength();
65     for (uint32_t j = 0; j < keysLen; j++) {
66         PropertyDescriptor desc(thread);
67         key.Update(keys->Get(j));
68         bool success = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(from), key, desc);
69         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
70 
71         if (success && desc.IsEnumerable()) {
72             JSTaggedValue value = desc.GetValue().GetTaggedValue();
73             if (value.IsUndefined() || JSHandle<JSTaggedValue>::Cast(from)->IsJSProxy()) {
74                 value = ObjectFastOperator::FastGetPropertyByValue(thread, from.GetTaggedValue(),
75                                                                    key.GetTaggedValue());
76             }
77             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
78 
79             ObjectFastOperator::FastSetPropertyByValue(thread, toAssign.GetTaggedValue(), key.GetTaggedValue(),
80                                                        value);
81             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
82         }
83     }
84     return JSTaggedValue::Undefined();
85 }
86 
87 // 19.1.2.1 Object.assign ( target, ...sources )
Assign(EcmaRuntimeCallInfo *argv)88 JSTaggedValue BuiltinsObject::Assign(EcmaRuntimeCallInfo *argv)
89 {
90     ASSERT(argv);
91     JSThread *thread = argv->GetThread();
92     BUILTINS_API_TRACE(thread, Object, Assign);
93     [[maybe_unused]] EcmaHandleScope handleScope(thread);
94 
95     uint32_t numArgs = argv->GetArgsNumber();
96     // 1.Let to be ToObject(target).
97     JSHandle<JSTaggedValue> target = GetCallArg(argv, 0);
98     JSHandle<JSObject> toAssign = JSTaggedValue::ToObject(thread, target);
99     // 2.ReturnIfAbrupt(to).
100     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
101 
102     // 3.If only one argument was passed, return to.
103     // 4.Let sources be the List of argument values starting with the second argument.
104     // 5.For each element nextSource of sources, in ascending index order
105     //   a.If nextSource is undefined or null, let keys be an empty List.
106     //   b.Else,
107     //     i.Let from be ToObject(nextSource).
108     //     ii.Let keys be from.[[OwnPropertyKeys]]().
109     //     iii.ReturnIfAbrupt(keys).
110     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
111     for (uint32_t i = 1; i < numArgs; i++) {
112         JSHandle<JSTaggedValue> source = GetCallArg(argv, i);
113         if (!source->IsNull() && !source->IsUndefined()) {
114             JSHandle<JSObject> from = JSTaggedValue::ToObject(thread, source);
115             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
116 
117             JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(from));
118             // ReturnIfAbrupt(keys)
119             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
120 
121             // c.Repeat for each element nextKey of keys in List order,
122             //    i.Let desc be from.[[GetOwnProperty]](nextKey).
123             //    ii.ReturnIfAbrupt(desc).
124             //    iii.if desc is not undefined and desc.[[Enumerable]] is true, then
125             //      1.Let propValue be Get(from, nextKey).
126             //      2.ReturnIfAbrupt(propValue).
127             //      3.Let status be Set(to, nextKey, propValue, true).
128             //      4.ReturnIfAbrupt(status).
129             uint32_t keysLen = keys->GetLength();
130             for (uint32_t j = 0; j < keysLen; j++) {
131                 PropertyDescriptor desc(thread);
132                 key.Update(keys->Get(j));
133                 bool success = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(from), key, desc);
134                 // ReturnIfAbrupt(desc)
135                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
136 
137                 if (success && desc.IsEnumerable()) {
138                     JSTaggedValue value = desc.GetValue().GetTaggedValue();
139                     if (value.IsUndefined() || JSHandle<JSTaggedValue>::Cast(from)->IsJSProxy()) {
140                         value = ObjectFastOperator::FastGetPropertyByValue(thread, from.GetTaggedValue(),
141                                                                            key.GetTaggedValue());
142                     }
143                     // ReturnIfAbrupt(prop_value)
144                     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
145 
146                     ObjectFastOperator::FastSetPropertyByValue(thread, toAssign.GetTaggedValue(), key.GetTaggedValue(),
147                                                                value);
148                     //  ReturnIfAbrupt(status)
149                     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
150                 }
151             }
152         }
153     }
154 
155     // 6.Return to.
156     return toAssign.GetTaggedValue();
157 }
158 
159 // Runtime Semantics
ObjectDefineProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &prop)160 JSTaggedValue BuiltinsObject::ObjectDefineProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
161                                                      const JSHandle<JSTaggedValue> &prop)
162 {
163     BUILTINS_API_TRACE(thread, Object, DefineProperties);
164     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
165     // 1.If Type(O) is not Object, throw a TypeError exception.
166     if (!obj->IsECMAObject()) {
167         // throw a TypeError exception
168         THROW_TYPE_ERROR_AND_RETURN(thread, "is not an object", JSTaggedValue::Exception());
169     }
170 
171     // 2.Let props be ToObject(Properties).
172     JSHandle<JSObject> props = JSTaggedValue::ToObject(thread, prop);
173 
174     // 3.ReturnIfAbrupt(props).
175     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
176 
177     // 4.Let keys be props.[[OwnPropertyKeys]]().
178     JSHandle<TaggedArray> handleKeys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(props));
179 
180     // 5.ReturnIfAbrupt(keys).
181     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
182 
183     // 6.Let descriptors be an empty List.
184     // new an empty array and append
185     uint32_t length = handleKeys->GetLength();
186     [[maybe_unused]] JSHandle<TaggedArray> descriptors =
187         factory->NewTaggedArray(2 * length);  // 2: 2 means two element list
188 
189     // 7.Repeat for each element nextKey of keys in List order,
190     //   a.Let propDesc be props.[[GetOwnProperty]](nextKey).
191     //   b.ReturnIfAbrupt(propDesc).
192     //   c.If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
193     //     i.Let descObj be Get( props, nextKey).
194     //     ii.ReturnIfAbrupt(descObj).
195     //     iii.Let desc be ToPropertyDescriptor(descObj).
196     //     iv.ReturnIfAbrupt(desc).
197     //     v.Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors.
198 
199     std::vector<PropertyDescriptor> desArr;
200     for (uint32_t i = 0; i < length; i++) {
201         PropertyDescriptor propDesc(thread);
202         JSHandle<JSTaggedValue> handleKey(thread, handleKeys->Get(i));
203 
204         bool success = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(props), handleKey, propDesc);
205         // ReturnIfAbrupt(propDesc)
206         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
207 
208         if (success && propDesc.IsEnumerable()) {
209             JSHandle<JSTaggedValue> descObj =
210                 JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(props), handleKey).GetValue();
211             // ReturnIfAbrupt(descObj)
212             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
213 
214             PropertyDescriptor desc(thread);
215             JSObject::ToPropertyDescriptor(thread, descObj, desc);
216             // ReturnIfAbrupt(desc)
217             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
218             desc.SetKey(handleKey);
219             desArr.emplace_back(desc);
220         }
221     }
222     uint32_t desLength = desArr.size();
223     for (uint32_t i = 0; i < desLength; i++) {
224         // 8.For each pair from descriptors in list order,
225         //   a.Let P be the first element of pair.
226         //   b.Let desc be the second element of pair.
227         //   c.Let status be DefinePropertyOrThrow(O,P, desc).
228         //   d.ReturnIfAbrupt(status).
229         [[maybe_unused]] bool setSuccess =
230             JSTaggedValue::DefinePropertyOrThrow(thread, obj, desArr[i].GetKey(), desArr[i]);
231 
232         // ReturnIfAbrupt(status)
233         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
234     }
235     // 9.Return O.
236     return obj.GetTaggedValue();
237 }
238 
239 // 19.1.2.2 Object.create ( O [ , Properties ] )
Create(EcmaRuntimeCallInfo *argv)240 JSTaggedValue BuiltinsObject::Create(EcmaRuntimeCallInfo *argv)
241 {
242     ASSERT(argv);
243     JSThread *thread = argv->GetThread();
244     BUILTINS_API_TRACE(thread, Object, Create);
245     [[maybe_unused]] EcmaHandleScope handleScope(thread);
246     // 1.If Type(O) is neither Object nor Null, throw a TypeError exception.
247     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
248     if (!obj->IsECMAObject() && !obj->IsNull()) {
249         // throw a TypeError exception
250         THROW_TYPE_ERROR_AND_RETURN(thread, "Create: O is neither Object nor Null", JSTaggedValue::Exception());
251     }
252 
253     if (obj->IsJSShared()) {
254         THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(CreateObjectWithSendableProto),
255                                     JSTaggedValue::Exception());
256     }
257 
258     JSHandle<JSTaggedValue> properties = GetCallArg(argv, 1);
259 
260     // 2.Let obj be ObjectCreate(O).
261     JSHandle<JSObject> objCreate = thread->GetEcmaVM()->GetFactory()->OrdinaryNewJSObjectCreate(obj);
262 
263     // 3.If the argument Properties is present and not undefined, then
264     //   a.Return ObjectDefineProperties(obj, Properties).
265     if (!properties->IsUndefined()) {
266         return ObjectDefineProperties(thread, JSHandle<JSTaggedValue>::Cast(objCreate), properties);
267     }
268 
269     // 4.Return obj.
270     return objCreate.GetTaggedValue();
271 }
272 
273 // 19.1.2.3 Object.defineProperties ( O, Properties )
DefineProperties(EcmaRuntimeCallInfo *argv)274 JSTaggedValue BuiltinsObject::DefineProperties(EcmaRuntimeCallInfo *argv)
275 {
276     ASSERT(argv);
277     JSThread *thread = argv->GetThread();
278     BUILTINS_API_TRACE(thread, Object, DefineProperties);
279     [[maybe_unused]] EcmaHandleScope handleScope(thread);
280     // 1.Return ObjectDefineProperties(O, Properties).
281     return ObjectDefineProperties(thread, GetCallArg(argv, 0), GetCallArg(argv, 1));
282 }
283 
284 // 19.1.2.4 Object.defineProperty ( O, P, Attributes )
DefineProperty(EcmaRuntimeCallInfo *argv)285 JSTaggedValue BuiltinsObject::DefineProperty(EcmaRuntimeCallInfo *argv)
286 {
287     ASSERT(argv);
288     JSThread *thread = argv->GetThread();
289     BUILTINS_API_TRACE(thread, Object, DefineProperty);
290     [[maybe_unused]] EcmaHandleScope handleScope(thread);
291 
292     // 1.If Type(O) is not Object, throw a TypeError exception.
293     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
294     if (!obj->IsECMAObject()) {
295         // throw a TypeError
296         THROW_TYPE_ERROR_AND_RETURN(thread, "DefineProperty: O is not Object", JSTaggedValue::Exception());
297     }
298 
299     // 2.Let key be ToPropertyKey(P).
300     JSHandle<JSTaggedValue> prop = GetCallArg(argv, 1);
301     JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, prop);
302 
303     // 3.ReturnIfAbrupt(key).
304     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
305     // 4.Let desc be ToPropertyDescriptor(Attributes).
306     PropertyDescriptor desc(thread);
307     JSObject::ToPropertyDescriptor(thread, GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD), desc);
308 
309     // 5.ReturnIfAbrupt(desc).
310     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
311 
312     // 6.Let success be DefinePropertyOrThrow(O,key, desc).
313     [[maybe_unused]] bool success = JSTaggedValue::DefinePropertyOrThrow(thread, obj, key, desc);
314 
315     // 7.ReturnIfAbrupt(success).
316     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
317     // 8.Return O.
318     return obj.GetTaggedValue();
319 }
320 
321 // 19.1.2.5 Object.freeze ( O )
Freeze(EcmaRuntimeCallInfo *argv)322 JSTaggedValue BuiltinsObject::Freeze(EcmaRuntimeCallInfo *argv)
323 {
324     ASSERT(argv);
325     JSThread *thread = argv->GetThread();
326     BUILTINS_API_TRACE(thread, Object, Freeze);
327 
328     // 1.If Type(O) is not Object, return O.
329     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
330     if (!obj->IsECMAObject()) {
331         return obj.GetTaggedValue();
332     }
333 
334     [[maybe_unused]] EcmaHandleScope handleScope(thread);
335     bool status = false;
336     // 2.Let status be SetIntegrityLevel( O, "frozen").
337     if (obj->IsJSSharedObject() || obj->IsJSSharedFunction() || obj->IsJSSharedAsyncFunction()) {
338         status = JSObject::FreezeSharedObject(thread, JSHandle<JSObject>(obj));
339     } else if (obj->IsJSSharedArray()) {
340         THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(UpdateSendableAttributes), JSTaggedValue::Exception());
341     } else {
342         status = JSObject::SetIntegrityLevel(thread, JSHandle<JSObject>(obj), IntegrityLevel::FROZEN);
343     }
344 
345     // 3.ReturnIfAbrupt(status).
346     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
347 
348     // 4.If status is false, throw a TypeError exception.
349     if (!status) {
350         // throw a TypeError exception
351         THROW_TYPE_ERROR_AND_RETURN(thread, "Freeze: freeze failed", JSTaggedValue::Exception());
352     }
353 
354     // 5.Return O.
355     return obj.GetTaggedValue();
356 }
357 
358 // 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
GetOwnPropertyDescriptor(EcmaRuntimeCallInfo *argv)359 JSTaggedValue BuiltinsObject::GetOwnPropertyDescriptor(EcmaRuntimeCallInfo *argv)
360 {
361     ASSERT(argv);
362     JSThread *thread = argv->GetThread();
363     BUILTINS_API_TRACE(thread, Object, GetOwnPropertyDescriptor);
364     [[maybe_unused]] EcmaHandleScope handleScope(thread);
365 
366     // 1.Let obj be ToObject(O).
367     JSHandle<JSTaggedValue> func = GetCallArg(argv, 0);
368     JSHandle<JSObject> handle = JSTaggedValue::ToObject(thread, func);
369 
370     // 2.ReturnIfAbrupt(obj).
371     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
372 
373     // 3.Let key be ToPropertyKey(P).
374     JSHandle<JSTaggedValue> prop = GetCallArg(argv, 1);
375     JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, prop);
376 
377     // 4.ReturnIfAbrupt(key).
378     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
379 
380     // 5.Let desc be obj.[[GetOwnProperty]](key).
381     PropertyDescriptor desc(thread);
382     JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(handle), key, desc);
383 
384     // 6.ReturnIfAbrupt(desc).
385     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
386 
387     // 7.Return FromPropertyDescriptor(desc).
388     JSHandle<JSTaggedValue> res = JSObject::FromPropertyDescriptor(thread, desc);
389     return res.GetTaggedValue();
390 }
391 
GetOwnPropertyDescriptors(EcmaRuntimeCallInfo *argv)392 JSTaggedValue BuiltinsObject::GetOwnPropertyDescriptors(EcmaRuntimeCallInfo *argv)
393 {
394     ASSERT(argv);
395     JSThread *thread = argv->GetThread();
396     BUILTINS_API_TRACE(thread, Object, GetOwnPropertyDescriptors);
397     [[maybe_unused]] EcmaHandleScope handleScope(thread);
398 
399     // 1.Let obj be ToObject(O).
400     JSHandle<JSTaggedValue> func = GetCallArg(argv, 0);
401     JSHandle<JSObject> handle = JSTaggedValue::ToObject(thread, func);
402 
403     // 2.ReturnIfAbrupt(obj).
404     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
405 
406     // 3. Let ownKeys be ? obj.[[OwnPropertyKeys]]().
407     JSHandle<TaggedArray> ownKeys =
408         JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>(handle));
409 
410     // 4.ReturnIfAbrupt(ownKeys).
411     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
412 
413     // 5.Let descriptors be OrdinaryObjectCreate(%Object.prototype%).
414     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
415     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
416     JSHandle<JSFunction> constructor(env->GetObjectFunction());
417     JSHandle<JSObject> descriptors = factory->NewJSObjectByConstructor(constructor);
418 
419     // 6.For each element key of ownKeys, do
420     // a. Let desc be ? obj.[[GetOwnProperty]](key).
421     // b. Let descriptor be FromPropertyDescriptor(desc).
422     // c. If descriptor is not undefined, perform ! CreateDataPropertyOrThrow(descriptors, key, descriptor).
423     uint32_t length = ownKeys->GetLength();
424     JSMutableHandle<JSTaggedValue> handleKey(thread, JSTaggedValue::Undefined());
425     for (uint32_t i = 0; i < length; ++i) {
426         handleKey.Update(ownKeys->Get(i));
427         PropertyDescriptor desc(thread);
428         JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(handle), handleKey, desc);
429         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
430         JSHandle<JSTaggedValue> descriptor = JSObject::FromPropertyDescriptor(thread, desc);
431         if (!descriptor->IsUndefined()) {
432             JSObject::CreateDataPropertyOrThrow(thread, descriptors, handleKey, descriptor);
433             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
434         }
435     }
436 
437     // 7.Return descriptors.
438     return descriptors.GetTaggedValue();
439 }
440 
441 // Runtime Semantics
GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &object, const KeyType &type)442 JSTaggedValue BuiltinsObject::GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &object,
443                                                  const KeyType &type)
444 {
445     BUILTINS_API_TRACE(thread, Object, GetOwnPropertyKeys);
446     // 1.Let obj be ToObject(O).
447     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
448     JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, object);
449 
450     // 2.ReturnIfAbrupt(obj).
451     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
452 
453     // 3.Let keys be obj.[[OwnPropertyKeys]]().
454     JSHandle<TaggedArray> handleKeys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(obj));
455 
456     // 4.ReturnIfAbrupt(keys).
457     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
458 
459     // 5.Let nameList be a new empty List.
460     // new an empty array and append
461     uint32_t length = handleKeys->GetLength();
462     JSHandle<TaggedArray> nameList = factory->NewTaggedArray(length);
463 
464     // 6.Repeat for each element nextKey of keys in List order,
465     uint32_t copyLength = 0;
466     switch (type) {
467         case KeyType::STRING_TYPE: {
468             for (uint32_t i = 0; i < length; i++) {
469                 JSTaggedValue key = handleKeys->Get(i);
470                 if (key.IsString()) {
471                     nameList->Set(thread, copyLength, key);
472                     copyLength++;
473                 }
474             }
475             break;
476         }
477         case KeyType::SYMBOL_TYPE: {
478             for (uint32_t i = 0; i < length; i++) {
479                 JSTaggedValue key = handleKeys->Get(i);
480                 if (key.IsSymbol()) {
481                     nameList->Set(thread, copyLength, key);
482                     copyLength++;
483                 }
484             }
485             break;
486         }
487         default:
488             break;
489     }
490 
491     // 7.Return CreateArrayFromList(nameList).
492     JSHandle<TaggedArray> resultList = factory->CopyArray(nameList, length, copyLength);
493     JSHandle<JSArray> resultArray = JSArray::CreateArrayFromList(thread, resultList);
494     return resultArray.GetTaggedValue();
495 }
496 
497 // 19.1.2.7 Object.getOwnPropertyNames ( O )
GetOwnPropertyNames(EcmaRuntimeCallInfo *argv)498 JSTaggedValue BuiltinsObject::GetOwnPropertyNames(EcmaRuntimeCallInfo *argv)
499 {
500     ASSERT(argv);
501     JSThread *thread = argv->GetThread();
502     BUILTINS_API_TRACE(thread, Object, GetOwnPropertyNames);
503     [[maybe_unused]] EcmaHandleScope handleScope(thread);
504     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
505     KeyType type = KeyType::STRING_TYPE;
506 
507     // 1.Return GetOwnPropertyKeys(O, String).
508     return GetOwnPropertyKeys(thread, obj, type);
509 }
510 
511 // 19.1.2.8 Object.getOwnPropertySymbols ( O )
GetOwnPropertySymbols(EcmaRuntimeCallInfo *argv)512 JSTaggedValue BuiltinsObject::GetOwnPropertySymbols(EcmaRuntimeCallInfo *argv)
513 {
514     ASSERT(argv);
515     JSThread *thread = argv->GetThread();
516     BUILTINS_API_TRACE(thread, Object, GetOwnPropertySymbols);
517     [[maybe_unused]] EcmaHandleScope handleScope(thread);
518     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
519     KeyType type = KeyType::SYMBOL_TYPE;
520 
521     // 1.Return GetOwnPropertyKeys(O, Symbol).
522     return GetOwnPropertyKeys(thread, obj, type);
523 }
524 
525 // 19.1.2.9 Object.getPrototypeOf ( O )
GetPrototypeOf(EcmaRuntimeCallInfo *argv)526 JSTaggedValue BuiltinsObject::GetPrototypeOf(EcmaRuntimeCallInfo *argv)
527 {
528     ASSERT(argv);
529     JSThread *thread = argv->GetThread();
530     BUILTINS_API_TRACE(thread, Object, GetPrototypeOf);
531     [[maybe_unused]] EcmaHandleScope handleScope(thread);
532 
533     // 1.Let obj be ToObject(O).
534     JSHandle<JSTaggedValue> func = GetCallArg(argv, 0);
535 
536     JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, func);
537 
538     // 2.ReturnIfAbrupt(obj).
539     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
540 
541     // 3.Return obj.[[GetPrototypeOf]]().
542     return JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(obj));
543 }
544 
545 // 19.1.2.10 Object.is ( value1, value2 )
Is(EcmaRuntimeCallInfo *argv)546 JSTaggedValue BuiltinsObject::Is(EcmaRuntimeCallInfo *argv)
547 {
548     ASSERT(argv);
549     BUILTINS_API_TRACE(argv->GetThread(), Object, Is);
550 
551     // 1.Return SameValue(value1, value2).
552     bool result = JSTaggedValue::SameValue(GetCallArg(argv, 0), GetCallArg(argv, 1));
553     return GetTaggedBoolean(result);
554 }
555 
556 // 19.1.2.11 Object.isExtensible ( O )
IsExtensible(EcmaRuntimeCallInfo *argv)557 JSTaggedValue BuiltinsObject::IsExtensible(EcmaRuntimeCallInfo *argv)
558 {
559     ASSERT(argv);
560     JSThread *thread = argv->GetThread();
561     BUILTINS_API_TRACE(thread, Object, IsExtensible);
562     // 1.If Type(O) is not Object, return false.
563     JSTaggedValue obj = GetCallArg(argv, 0).GetTaggedValue();
564     if (!obj.IsHeapObject()) {
565         return GetTaggedBoolean(false);
566     }
567     [[maybe_unused]] EcmaHandleScope handleScope(thread);
568     // 2.Return IsExtensible(O).
569     return GetTaggedBoolean(obj.IsExtensible(thread));
570 }
571 
572 // 19.1.2.12 Object.isFrozen ( O )
IsFrozen(EcmaRuntimeCallInfo *argv)573 JSTaggedValue BuiltinsObject::IsFrozen(EcmaRuntimeCallInfo *argv)
574 {
575     ASSERT(argv);
576     BUILTINS_API_TRACE(argv->GetThread(), Object, IsFrozen);
577     // 1.If Type(O) is not Object, return true.
578     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
579     if (!obj->IsECMAObject()) {
580         return GetTaggedBoolean(true);
581     }
582 
583     JSThread *thread = argv->GetThread();
584     [[maybe_unused]] EcmaHandleScope handleScope(thread);
585 
586     // 2.Return TestIntegrityLevel(O, "frozen").
587     bool status = JSObject::TestIntegrityLevel(thread, JSHandle<JSObject>(obj), IntegrityLevel::FROZEN);
588     return GetTaggedBoolean(status);
589 }
590 
591 // 19.1.2.13 Object.isSealed ( O )
IsSealed(EcmaRuntimeCallInfo *argv)592 JSTaggedValue BuiltinsObject::IsSealed(EcmaRuntimeCallInfo *argv)
593 {
594     ASSERT(argv);
595     BUILTINS_API_TRACE(argv->GetThread(), Object, IsSealed);
596     // 1.If Type(O) is not Object, return true.
597     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
598     if (!obj->IsECMAObject()) {
599         return GetTaggedBoolean(true);
600     }
601 
602     JSThread *thread = argv->GetThread();
603     [[maybe_unused]] EcmaHandleScope handleScope(thread);
604 
605     // 2.Return TestIntegrityLevel(O, "sealed").
606     bool status = JSObject::TestIntegrityLevel(thread, JSHandle<JSObject>(obj), IntegrityLevel::SEALED);
607     return GetTaggedBoolean(status);
608 }
609 
610 // 19.1.2.14 Object.keys(O)
Keys(EcmaRuntimeCallInfo *argv)611 JSTaggedValue BuiltinsObject::Keys(EcmaRuntimeCallInfo *argv)
612 {
613     ASSERT(argv);
614     JSThread *thread = argv->GetThread();
615     BUILTINS_API_TRACE(thread, Object, Keys);
616     [[maybe_unused]] EcmaHandleScope handleScope(thread);
617 
618     // 1. Let obj be ToObject(O).
619     JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0);
620 
621     JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, msg);
622 
623     // 2. ReturnIfAbrupt(obj).
624     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
625 
626     // 3. Let nameList be EnumerableOwnNames(obj).
627     JSHandle<TaggedArray> nameList = JSObject::EnumerableOwnNames(thread, obj);
628 
629     // 4. ReturnIfAbrupt(nameList).
630     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
631 
632     // 5. Return CreateArrayFromList(nameList).
633     JSHandle<JSArray> result = JSArray::CreateArrayFromList(thread, nameList);
634     return result.GetTaggedValue();
635 }
636 
637 // 20.1.2.22 Object.values(O)
Values(EcmaRuntimeCallInfo *argv)638 JSTaggedValue BuiltinsObject::Values(EcmaRuntimeCallInfo *argv)
639 {
640     ASSERT(argv);
641     JSThread *thread = argv->GetThread();
642     BUILTINS_API_TRACE(thread, Object, Values);
643     [[maybe_unused]] EcmaHandleScope handleScope(thread);
644 
645     // 1. Let obj be ToObject(O).
646     JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0);
647     JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, msg);
648 
649     // 2. ReturnIfAbrupt(obj).
650     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
651 
652     // 3. Let nameList be ? EnumerableOwnPropertyNames(obj, value).
653     JSHandle<TaggedArray> nameList = JSObject::EnumerableOwnPropertyNames(thread, obj, PropertyKind::VALUE);
654 
655     // 4. ReturnIfAbrupt(nameList).
656     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
657 
658     // 5. Return CreateArrayFromList(nameList).
659     JSHandle<JSArray> result = JSArray::CreateArrayFromList(thread, nameList);
660     return result.GetTaggedValue();
661 }
662 
663 // 19.1.2.15 Object.preventExtensions(O)
PreventExtensions(EcmaRuntimeCallInfo *argv)664 JSTaggedValue BuiltinsObject::PreventExtensions(EcmaRuntimeCallInfo *argv)
665 {
666     ASSERT(argv);
667     JSThread *thread = argv->GetThread();
668     BUILTINS_API_TRACE(thread, Object, PreventExtensions);
669     // 1. If Type(O) is not Object, return O.
670     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
671     if (!obj->IsECMAObject()) {
672         return obj.GetTaggedValue();
673     }
674     [[maybe_unused]] EcmaHandleScope handleScope(thread);
675     // 2. Let status be O.[[PreventExtensions]]().
676     bool status = JSTaggedValue::PreventExtensions(thread, obj);
677 
678     // 3. ReturnIfAbrupt(status).
679     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
680 
681     // 4. If status is false, throw a TypeError exception.
682     if (!status) {
683         // throw a TypeError exception.
684         THROW_TYPE_ERROR_AND_RETURN(thread, "PreventExtensions: preventExtensions failed",
685                                     JSTaggedValue::Exception());
686     }
687 
688     // 5. Return O.
689     return obj.GetTaggedValue();
690 }
691 // 19.1.2.16 Object.prototype
692 
693 // 19.1.2.17 Object.seal(O)
Seal(EcmaRuntimeCallInfo *argv)694 JSTaggedValue BuiltinsObject::Seal(EcmaRuntimeCallInfo *argv)
695 {
696     ASSERT(argv);
697     JSThread *thread = argv->GetThread();
698     BUILTINS_API_TRACE(thread, Object, Seal);
699 
700     // 1. If Type(O) is not Object, return O.
701     JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0);
702     if (!msg->IsECMAObject()) {
703         return msg.GetTaggedValue();
704     }
705 
706     [[maybe_unused]] EcmaHandleScope handleScope(thread);
707 
708     // 2. Let status be SetIntegrityLevel(O, "sealed").
709     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, msg);
710     bool status = JSObject::SetIntegrityLevel(thread, object, IntegrityLevel::SEALED);
711 
712     // 3. ReturnIfAbrupt(status).
713     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
714 
715     // 4. If status is false, throw a TypeError exception.
716     if (!status) {
717         // throw a TypeError exception.
718         THROW_TYPE_ERROR_AND_RETURN(thread, "Seal: seal failed", JSTaggedValue::Exception());
719     }
720 
721     // 5. Return O.
722     return object.GetTaggedValue();
723 }
724 
725 // 19.1.2.18 Object.setPrototypeOf(O, proto)
SetPrototypeOf(EcmaRuntimeCallInfo *argv)726 JSTaggedValue BuiltinsObject::SetPrototypeOf(EcmaRuntimeCallInfo *argv)
727 {
728     ASSERT(argv);
729     JSThread *thread = argv->GetThread();
730     BUILTINS_API_TRACE(thread, Object, SetPrototypeOf);
731     [[maybe_unused]] EcmaHandleScope handleScope(thread);
732     // 1. Let O be RequireObjectCoercible(O).
733     JSHandle<JSTaggedValue> object = JSTaggedValue::RequireObjectCoercible(thread, GetCallArg(argv, 0));
734 
735     // 2. ReturnIfAbrupt(O).
736     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
737 
738     // 3. If Type(proto) is neither Object nor Null, throw a TypeError exception.
739     JSHandle<JSTaggedValue> proto = GetCallArg(argv, 1);
740     if (!proto->IsNull() && !proto->IsECMAObject()) {
741         // throw a TypeError exception.
742         THROW_TYPE_ERROR_AND_RETURN(thread, "SetPrototypeOf: proto is neither Object nor Null",
743                                     JSTaggedValue::Exception());
744     }
745 
746     // 4. If Type(O) is not Object, return O.
747     if (!object->IsECMAObject()) {
748         return object.GetTaggedValue();
749     }
750 
751     // 5. Let status be O.[[SetPrototypeOf]](proto).
752     bool status = JSTaggedValue::SetPrototype(thread, object, proto);
753 
754     // 6. ReturnIfAbrupt(status).
755     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
756 
757     // 7. If status is false, throw a TypeError exception.
758     if (!status) {
759         // throw a TypeError exception.
760         THROW_TYPE_ERROR_AND_RETURN(thread, "SetPrototypeOf: prototype set failed", JSTaggedValue::Exception());
761     }
762 
763     // 8. Return O.
764     return object.GetTaggedValue();
765 }
766 
767 // 19.1.3.1 Object.prototype.constructor
768 
769 // 19.1.3.2 Object.prototype.hasOwnProperty(V)
HasOwnProperty(EcmaRuntimeCallInfo *argv)770 JSTaggedValue BuiltinsObject::HasOwnProperty(EcmaRuntimeCallInfo *argv)
771 {
772     ASSERT(argv);
773     JSThread *thread = argv->GetThread();
774     BUILTINS_API_TRACE(thread, Object, HasOwnProperty);
775     [[maybe_unused]] EcmaHandleScope handleScope(thread);
776     JSHandle<JSTaggedValue> thisValue = GetThis(argv);
777     JSHandle<JSTaggedValue> prop = GetCallArg(argv, 0);
778     return HasOwnPropertyInternal(thread, thisValue, prop);
779 }
780 
HasOwnPropertyInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue, JSHandle<JSTaggedValue> prop)781 JSTaggedValue BuiltinsObject::HasOwnPropertyInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue,
782                                                      JSHandle<JSTaggedValue> prop)
783 {
784     [[maybe_unused]] EcmaHandleScope handleScope(thread);
785     std::pair<JSTaggedValue, bool> result = ObjectFastOperator::HasOwnProperty(thread, thisValue.GetTaggedValue(),
786         prop.GetTaggedValue());
787     if (!result.first.IsHole()) {
788         return GetTaggedBoolean(true);
789     } else if (result.second) {
790         return GetTaggedBoolean(false);
791     }
792 
793     // 1. Let P be ToPropertyKey(V).
794     JSHandle<JSTaggedValue> property = JSTaggedValue::ToPropertyKey(thread, prop);
795 
796     // 2. ReturnIfAbrupt(P).
797     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
798 
799     // 3. Let O be ToObject(this value).
800     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, thisValue);
801 
802     // 4. ReturnIfAbrupt(O).
803     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
804 
805     // 5. Return HasOwnProperty(O, P).
806     bool res = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(object), property);
807     return GetTaggedBoolean(res);
808 }
809 
810 // 19.1.3.3 Object.prototype.isPrototypeOf(V)
IsPrototypeOf(EcmaRuntimeCallInfo *argv)811 JSTaggedValue BuiltinsObject::IsPrototypeOf(EcmaRuntimeCallInfo *argv)
812 {
813     ASSERT(argv);
814     JSThread *thread = argv->GetThread();
815     BUILTINS_API_TRACE(thread, Object, IsPrototypeOf);
816     // 1. If Type(V) is not Object, return false.
817     JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0);
818     if (!msg->IsECMAObject()) {
819         return GetTaggedBoolean(false);
820     }
821     [[maybe_unused]] EcmaHandleScope handleScope(thread);
822     // 2. Let O be ToObject(this value).
823     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv));
824     // 3. ReturnIfAbrupt(O).
825     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
826 
827     // 4. Repeat
828     //    a. Let V be V.[[GetPrototypeOf]]().
829     //    b. If V is null, return false
830     //    c. If SameValue(O, V) is true, return true.
831     JSMutableHandle<JSTaggedValue> msgValueHandle(thread, msg.GetTaggedValue());
832     while (!msgValueHandle->IsNull()) {
833         msgValueHandle.Update(JSTaggedValue::GetPrototype(thread, msgValueHandle));
834         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
835 
836         if (JSTaggedValue::SameValue(object.GetTaggedValue(), msgValueHandle.GetTaggedValue())) {
837             return GetTaggedBoolean(true);
838         }
839     }
840     return GetTaggedBoolean(false);
841 }
842 
843 // 19.1.3.4 Object.prototype.propertyIsEnumerable(V)
PropertyIsEnumerable(EcmaRuntimeCallInfo *argv)844 JSTaggedValue BuiltinsObject::PropertyIsEnumerable(EcmaRuntimeCallInfo *argv)
845 {
846     ASSERT(argv);
847     // 1. Let P be ToPropertyKey(V).
848     JSThread *thread = argv->GetThread();
849     BUILTINS_API_TRACE(thread, Object, PropertyIsEnumerable);
850     [[maybe_unused]] EcmaHandleScope handleScope(thread);
851     JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0);
852     JSHandle<JSTaggedValue> property = JSTaggedValue::ToPropertyKey(thread, msg);
853 
854     // 2. ReturnIfAbrupt(P).
855     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
856 
857     // 3. Let O be ToObject(this value).
858     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv));
859     // 4. ReturnIfAbrupt(O).
860     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
861 
862     // 5. Let desc be O.[[GetOwnProperty]](P).
863     PropertyDescriptor desc(thread);
864     JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(object), property, desc);
865 
866     // 6. ReturnIfAbrupt(desc).
867     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
868 
869     // 7. If desc is undefined, return false.
870     if (desc.IsEmpty()) {
871         return GetTaggedBoolean(false);
872     }
873 
874     // 8. Return the value of desc.[[Enumerable]].
875     return GetTaggedBoolean(desc.IsEnumerable());
876 }
877 
878 // 19.1.3.5 Object.prototype.toLocaleString([reserved1[, reserved2]])
ToLocaleString(EcmaRuntimeCallInfo *argv)879 JSTaggedValue BuiltinsObject::ToLocaleString(EcmaRuntimeCallInfo *argv)
880 {
881     ASSERT(argv);
882     JSThread *thread = argv->GetThread();
883     BUILTINS_API_TRACE(thread, Object, ToLocaleString);
884     [[maybe_unused]] EcmaHandleScope handleScope(thread);
885     // 1. Let O be the this value.
886     JSHandle<JSTaggedValue> object = GetThis(argv);
887     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
888 
889     // 2. Return Invoke(O, "toString").
890     JSHandle<JSTaggedValue> calleeKey = thread->GlobalConstants()->GetHandledToStringString();
891     const uint32_t argsLength = argv->GetArgsNumber();
892     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
893     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, object, undefined, argsLength);
894     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
895     info->SetCallArg(argsLength, 0, argv, 0);
896     return JSFunction::Invoke(info, calleeKey);
897 }
898 
GetBuiltinObjectToString(JSThread *thread, const JSHandle<JSObject> &object)899 JSTaggedValue BuiltinsObject::GetBuiltinObjectToString(JSThread *thread, const JSHandle<JSObject> &object)
900 {
901     BUILTINS_API_TRACE(thread, Object, GetBuiltinObjectToString);
902     // 4. Let isArray be IsArray(O).
903     bool isArray = object.GetTaggedValue().IsArray(thread);
904     // 5. ReturnIfAbrupt(isArray).
905     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
906 
907     if (isArray) {
908         // 6. If isArray is true, return "[object Array]".
909         return thread->GlobalConstants()->GetArrayToString();
910     } else if (object->IsJSPrimitiveRef()) {
911         // 7. Else, if O is an exotic String object, return "[object String]".
912         JSPrimitiveRef *primitiveRef = JSPrimitiveRef::Cast(*object);
913         if (primitiveRef->IsString()) {
914             return thread->GlobalConstants()->GetStringToString();
915         } else if (primitiveRef->IsBoolean()) {
916             // 11. Else, if O has a [[BooleanData]] internal slot, return "[object Boolean]".
917             return thread->GlobalConstants()->GetBooleanToString();
918         } else if (primitiveRef->IsNumber()) {
919             // 12. Else, if O has a [[NumberData]] internal slot, return "[object Number]".
920             return thread->GlobalConstants()->GetNumberToString();
921         }
922     } else if (object->IsArguments()) {
923         // if O has a [[ArgumentsData]] internal slot, return "[object Arguments]".
924         return thread->GlobalConstants()->GetArgumentsToString();
925     } else if (object->IsCallable()) {
926         // if O has a [[CallableData]] internal slot, return "[object Function]".
927         return thread->GlobalConstants()->GetFunctionToString();
928     } else if (object->IsJSError()) {
929         // if O has a [[ErrorData]] internal slot, return "[object Error]".
930         return thread->GlobalConstants()->GetErrorToString();
931     } else if (object->IsDate()) {
932         // if O has a [[DateData]] internal slot, return "[object Date]".
933         return thread->GlobalConstants()->GetDateToString();
934     } else if (object->IsJSRegExp()) {
935         // if O has a [[RegExpData]] internal slot, return "[object JSRegExp]".
936         return thread->GlobalConstants()->GetRegExpToString();
937     }
938     // 15. Else, return "[Object Object]".
939     return thread->GlobalConstants()->GetObjectToString();
940 }
941 
942 // 19.1.3.6 Object.prototype.toString()
ToString(EcmaRuntimeCallInfo *argv)943 JSTaggedValue BuiltinsObject::ToString(EcmaRuntimeCallInfo *argv)
944 {
945     ASSERT(argv);
946     JSThread *thread = argv->GetThread();
947     BUILTINS_API_TRACE(thread, Object, ToString);
948     [[maybe_unused]] EcmaHandleScope handleScope(thread);
949     // 1. If the this value is undefined, return "[object Undefined]".
950 
951     JSHandle<JSTaggedValue> msg = GetThis(argv);
952     if (msg->IsUndefined()) {
953         return thread->GlobalConstants()->GetUndefinedToString();
954     }
955     // 2. If the this value is null, return "[object Null]".
956     if (msg->IsNull()) {
957         return thread->GlobalConstants()->GetNullToString();
958     }
959 
960     // 3. Let O be ToObject(this value).
961     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv));
962     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
963 
964     // 16. Let tag be Get (O, @@toStringTag).
965     auto ecmaVm = thread->GetEcmaVM();
966     JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
967     auto factory = ecmaVm->GetFactory();
968 
969     JSHandle<JSTaggedValue> tag = JSTaggedValue::GetProperty(thread, msg, env->GetToStringTagSymbol()).GetValue();
970 
971     // 17. ReturnIfAbrupt(tag).
972     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
973 
974     // 18. If Type(tag) is not String, return builtin object to string.
975     if (!tag->IsString()) {
976         return GetBuiltinObjectToString(thread, object);
977     }
978 
979     // 19. Return the String that is the result of concatenating "[object ", tag, and "]".
980     JSHandle<EcmaString> leftString(factory->NewFromASCII("[object "));
981     JSHandle<EcmaString> rightString(factory->NewFromASCII("]"));
982 
983     JSHandle<EcmaString> newLeftStringHandle =
984         factory->ConcatFromString(leftString, JSTaggedValue::ToString(thread, tag));
985     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
986     auto result = factory->ConcatFromString(newLeftStringHandle, rightString);
987     return result.GetTaggedValue();
988 }
989 
990 // 19.1.3.7 Object.prototype.valueOf()
ValueOf(EcmaRuntimeCallInfo *argv)991 JSTaggedValue BuiltinsObject::ValueOf(EcmaRuntimeCallInfo *argv)
992 {
993     ASSERT(argv);
994     JSThread *thread = argv->GetThread();
995     BUILTINS_API_TRACE(thread, Object, ValueOf);
996     [[maybe_unused]] EcmaHandleScope handleScope(thread);
997 
998     // 1. Return ToObject(this value).
999     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv));
1000     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1001     return object.GetTaggedValue();
1002 }
1003 // B.2.2.1 Object.prototype.__proto__
ProtoGetter(EcmaRuntimeCallInfo *argv)1004 JSTaggedValue BuiltinsObject::ProtoGetter(EcmaRuntimeCallInfo *argv)
1005 {
1006     ASSERT(argv);
1007     JSThread *thread = argv->GetThread();
1008     BUILTINS_API_TRACE(thread, Object, ProtoGetter);
1009     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1010 
1011     // 1.Let obj be ToObject(this value).
1012     JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, GetThis(argv));
1013 
1014     // 2.ReturnIfAbrupt(obj).
1015     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1016 
1017     // 3.Return obj.[[GetPrototypeOf]]().
1018     return JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(obj));
1019 }
1020 
ProtoSetter(EcmaRuntimeCallInfo *argv)1021 JSTaggedValue BuiltinsObject::ProtoSetter(EcmaRuntimeCallInfo *argv)
1022 {
1023     ASSERT(argv);
1024     JSThread *thread = argv->GetThread();
1025     BUILTINS_API_TRACE(thread, Object, ProtoSetter);
1026     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1027     // 1. Let O be RequireObjectCoercible(this value).
1028     JSHandle<JSTaggedValue> obj = JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv));
1029 
1030     // 2. ReturnIfAbrupt(O).
1031     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1032 
1033     // 3. If Type(proto) is neither Object nor Null, return undefined..
1034     JSHandle<JSTaggedValue> proto = GetCallArg(argv, 0);
1035     if (!proto->IsNull() && !proto->IsECMAObject()) {
1036         return JSTaggedValue::Undefined();
1037     }
1038 
1039     // 4. If Type(O) is not Object, return undefined.
1040     if (!obj->IsECMAObject()) {
1041         return JSTaggedValue::Undefined();
1042     }
1043 
1044     // 5. Let status be O.[[SetPrototypeOf]](proto).
1045     bool status = JSTaggedValue::SetPrototype(thread, obj, proto, true);
1046 
1047     // 6. ReturnIfAbrupt(status).
1048     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1049 
1050     // 7. If status is false, throw a TypeError exception.
1051     if (!status) {
1052         // throw a TypeError exception.
1053         THROW_TYPE_ERROR_AND_RETURN(thread, "ProtoSetter: proto set failed", JSTaggedValue::Exception());
1054     }
1055 
1056     // 8. Return O.
1057     return JSTaggedValue::Undefined();
1058 }
1059 
CreateRealm(EcmaRuntimeCallInfo *argv)1060 JSTaggedValue BuiltinsObject::CreateRealm(EcmaRuntimeCallInfo *argv)
1061 {
1062     ASSERT(argv);
1063     JSThread *thread = argv->GetThread();
1064     BUILTINS_API_TRACE(thread, Object, CreateRealm);
1065     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1066     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1067     JSHandle<JSRealm> realm = factory->NewJSRealm();
1068     return realm.GetTaggedValue();
1069 }
1070 
Entries(EcmaRuntimeCallInfo *argv)1071 JSTaggedValue BuiltinsObject::Entries(EcmaRuntimeCallInfo *argv)
1072 {
1073     ASSERT(argv);
1074     JSThread *thread = argv->GetThread();
1075     BUILTINS_API_TRACE(thread, Object, ToString);
1076     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1077 
1078     // 1. Let obj be ? ToObject(O).
1079     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
1080     if (obj->IsJSUint8Array() || obj->IsJSUint16Array()) {
1081         THROW_RANGE_ERROR_AND_RETURN(thread, "Object entries is not supported IsJSUint8Array or IsJSUint16Array",
1082                                      JSTaggedValue::Exception());
1083     }
1084     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, obj);
1085     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1086     // 2. Let nameList be ? EnumerableOwnPropertyNames(obj, key+value).
1087     JSHandle<TaggedArray> nameList = JSObject::EnumerableOwnPropertyNames(thread, object, PropertyKind::KEY_VALUE);
1088     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1089     // 3. Return CreateArrayFromList(nameList).
1090     return JSArray::CreateArrayFromList(thread, nameList).GetTaggedValue();
1091 }
1092 
FromEntries(EcmaRuntimeCallInfo *argv)1093 JSTaggedValue BuiltinsObject::FromEntries(EcmaRuntimeCallInfo *argv)
1094 {
1095     ASSERT(argv);
1096     JSThread *thread = argv->GetThread();
1097     BUILTINS_API_TRACE(thread, Object, FromEntries);
1098     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1099 
1100     JSHandle<JSTaggedValue> iterable = GetCallArg(argv, 0);
1101     // 1. Perform ? RequireObjectCoercible(iterable).
1102     if (iterable->IsUndefined() || iterable->IsNull()) {
1103         THROW_TYPE_ERROR_AND_RETURN(thread, "iterable is undefined or null", JSTaggedValue::Exception());
1104     }
1105 
1106     // 2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%).
1107     // 3. Assert: obj is an extensible ordinary object with no own properties.
1108     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1109     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1110     JSHandle<JSFunction> constructor(env->GetObjectFunction());
1111     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(constructor);
1112 
1113     // 4. Let stepsDefine be the algorithm steps defined in CreateDataPropertyOnObject Functions.
1114     // 5. Let lengthDefine be the number of non-optional parameters of the function definition in
1115     //    CreateDataPropertyOnObject Functions.
1116     // 6. Let adder be ! CreateBuiltinFunction(stepsDefine, lengthDefine, "", « »).
1117     JSHandle<Method> method(thread,
1118         thread->GetEcmaVM()->GetMethodByIndex(MethodIndex::BUILTINS_OBJECT_CREATE_DATA_PROPERTY_ON_OBJECT_FUNCTIONS));
1119     JSHandle<JSFunction> addrFunc = factory->NewJSFunction(env, method);
1120 
1121     JSHandle<JSTaggedValue> adder(thread, addrFunc.GetTaggedValue());
1122 
1123     // 7. Return ? AddEntriesFromIterable(obj, iterable, adder).
1124     return BuiltinsMap::AddEntriesFromIterable(thread, obj, iterable, adder, factory);
1125 }
1126 
CreateDataPropertyOnObjectFunctions(EcmaRuntimeCallInfo *argv)1127 JSTaggedValue BuiltinsObject::CreateDataPropertyOnObjectFunctions(EcmaRuntimeCallInfo *argv)
1128 {
1129     ASSERT(argv);
1130     JSThread *thread = argv->GetThread();
1131     BUILTINS_API_TRACE(thread, Object, CreateDataPropertyOnObjectFunctions);
1132     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1133 
1134     // 1. Let O be the this value.
1135     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1136     JSHandle<JSObject> thisObjHandle = JSHandle<JSObject>::Cast(thisHandle);
1137 
1138     // 2. Assert: Type(O) is Object.
1139     // 3. Assert: O is an extensible ordinary object.
1140     ASSERT(thisHandle->IsHeapObject());
1141 
1142     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
1143     JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
1144 
1145     // 4. Let propertyKey be ? ToPropertyKey(key).
1146     JSHandle<JSTaggedValue> propertyKey = JSTaggedValue::ToPropertyKey(thread, key);
1147     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1148 
1149     // 5. Perform ! CreateDataPropertyOrThrow(O, propertyKey, value).
1150     JSObject::CreateDataPropertyOrThrow(thread, thisObjHandle, propertyKey, value);
1151     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1152 
1153     // 6. Return undefined.
1154     return JSTaggedValue::Undefined();
1155 }
1156 
HasOwn(EcmaRuntimeCallInfo *argv)1157 JSTaggedValue BuiltinsObject::HasOwn(EcmaRuntimeCallInfo *argv)
1158 {
1159     ASSERT(argv);
1160     JSThread *thread = argv->GetThread();
1161     BUILTINS_API_TRACE(thread, Object, HasOwn);
1162     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1163 
1164     // 1. Let obj be ? ToObject(O).
1165     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
1166     JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, obj);
1167 
1168     // 2.ReturnIfAbrupt(obj).
1169     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1170 
1171     // 3.Let key be ToPropertyKey(P).
1172     JSHandle<JSTaggedValue> prop = GetCallArg(argv, 1);
1173     JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, prop);
1174 
1175     // 4. ReturnIfAbrupt(4).
1176     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1177 
1178     // 5. Return HasOwnProperty(O, P).
1179     bool res = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(object), key);
1180     return GetTaggedBoolean(res);
1181 }
1182 }  // namespace panda::ecmascript::builtins
1183