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