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