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
23namespace panda::ecmascript::builtins {
24// 19.1.1.1 Object ( [ value ] )
25JSTaggedValue 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
56JSTaggedValue 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 )
88JSTaggedValue 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
160JSTaggedValue 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 ] )
240JSTaggedValue 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 )
274JSTaggedValue 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 )
285JSTaggedValue 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 )
322JSTaggedValue 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 )
359JSTaggedValue 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
392JSTaggedValue 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
442JSTaggedValue 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 )
498JSTaggedValue 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 )
512JSTaggedValue 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 )
526JSTaggedValue 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 )
546JSTaggedValue 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 )
557JSTaggedValue 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 )
573JSTaggedValue 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 )
592JSTaggedValue 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)
611JSTaggedValue 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)
638JSTaggedValue 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)
664JSTaggedValue 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)
694JSTaggedValue 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)
726JSTaggedValue 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)
770JSTaggedValue 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
781JSTaggedValue 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)
811JSTaggedValue 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)
844JSTaggedValue 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]])
879JSTaggedValue 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
899JSTaggedValue 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()
943JSTaggedValue 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()
991JSTaggedValue 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__
1004JSTaggedValue 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
1021JSTaggedValue 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
1060JSTaggedValue 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
1071JSTaggedValue 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
1093JSTaggedValue 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
1127JSTaggedValue 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
1157JSTaggedValue 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