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