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