/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecma_string_table.h" #include "ecma_vm.h" #include "ecmascript/accessor_data.h" #include "ecmascript/base/error_helper.h" #include "ecmascript/builtins.h" #include "ecmascript/builtins/builtins_collator.h" #include "ecmascript/builtins/builtins_date_time_format.h" #include "ecmascript/builtins/builtins_errors.h" #include "ecmascript/builtins/builtins_global.h" #include "ecmascript/builtins/builtins_number_format.h" #include "ecmascript/builtins/builtins_promise.h" #include "ecmascript/builtins/builtins_promise_handler.h" #include "ecmascript/builtins/builtins_object.h" #include "ecmascript/builtins/builtins_proxy.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/free_object.h" #include "ecmascript/global_env.h" #include "ecmascript/global_env_constants-inl.h" #include "ecmascript/global_env_constants.h" #include "ecmascript/ic/ic_handler.h" #include "ecmascript/ic/profile_type_info.h" #include "ecmascript/ic/property_box.h" #include "ecmascript/ic/proto_change_details.h" #include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/jobs/pending_job.h" #include "ecmascript/jspandafile/class_info_extractor.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/js_api_arraylist.h" #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque.h" #include "ecmascript/js_api_deque_iterator.h" #include "ecmascript/js_api_linked_list.h" #include "ecmascript/js_api_linked_list_iterator.h" #include "ecmascript/js_api_list.h" #include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue.h" #include "ecmascript/js_api_queue_iterator.h" #include "ecmascript/js_api_stack.h" #include "ecmascript/js_api_stack_iterator.h" #include "ecmascript/js_api_tree_map.h" #include "ecmascript/js_api_tree_map_iterator.h" #include "ecmascript/js_api_tree_set.h" #include "ecmascript/js_api_tree_set_iterator.h" #include "ecmascript/js_api_vector.h" #include "ecmascript/js_api_vector_iterator.h" #include "ecmascript/js_arguments.h" #include "ecmascript/js_array.h" #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_arraybuffer.h" #include "ecmascript/js_async_function.h" #include "ecmascript/js_bigint.h" #include "ecmascript/js_collator.h" #include "ecmascript/js_dataview.h" #include "ecmascript/js_date.h" #include "ecmascript/js_date_time_format.h" #include "ecmascript/js_displaynames.h" #include "ecmascript/js_list_format.h" #include "ecmascript/js_finalization_registry.h" #include "ecmascript/js_for_in_iterator.h" #include "ecmascript/js_generator_object.h" #include "ecmascript/js_hclass-inl.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_iterator.h" #include "ecmascript/js_map.h" #include "ecmascript/js_map_iterator.h" #include "ecmascript/js_number_format.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_plural_rules.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_proxy.h" #include "ecmascript/js_realm.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_regexp_iterator.h" #include "ecmascript/js_relative_time_format.h" #include "ecmascript/js_set.h" #include "ecmascript/js_set_iterator.h" #include "ecmascript/js_string_iterator.h" #include "ecmascript/js_symbol.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" #include "ecmascript/js_typed_array.h" #include "ecmascript/js_weak_container.h" #include "ecmascript/js_weak_ref.h" #include "ecmascript/layout_info-inl.h" #include "ecmascript/linked_hash_table.h" #include "ecmascript/mem/heap-inl.h" #include "ecmascript/mem/space.h" #include "ecmascript/module/js_module_namespace.h" #include "ecmascript/module/js_module_source_text.h" #include "ecmascript/record.h" #include "ecmascript/shared_mm/shared_mm.h" #include "ecmascript/symbol_table.h" #include "ecmascript/tagged_list.h" #include "ecmascript/tagged_tree.h" #include "ecmascript/template_map.h" #include "ecmascript/ts_types/ts_obj_layout_info.h" #include "ecmascript/ts_types/ts_type.h" #include "ecmascript/ts_types/ts_type_table.h" #include "ecmascript/require/js_cjs_exports.h" #include "ecmascript/require/js_cjs_module.h" #include "ecmascript/require/js_cjs_require.h" namespace panda::ecmascript { using Error = builtins::BuiltinsError; using RangeError = builtins::BuiltinsRangeError; using ReferenceError = builtins::BuiltinsReferenceError; using TypeError = builtins::BuiltinsTypeError; using URIError = builtins::BuiltinsURIError; using SyntaxError = builtins::BuiltinsSyntaxError; using EvalError = builtins::BuiltinsEvalError; using ErrorType = base::ErrorType; using ErrorHelper = base::ErrorHelper; ObjectFactory::ObjectFactory(JSThread *thread, Heap *heap, Chunk *chunk) : thread_(thread), vm_(thread->GetEcmaVM()), heap_(heap), nativeMethods_(chunk), internalNativeMethods_(chunk) { } ObjectFactory::~ObjectFactory() { ClearNativeMethodsData(); } void ObjectFactory::ClearNativeMethodsData() { for (auto iter : nativeMethods_) { vm_->GetChunk()->Delete(iter); } nativeMethods_.clear(); for (auto iter : internalNativeMethods_) { vm_->GetChunk()->Delete(iter); } internalNativeMethods_.clear(); } JSMethod *ObjectFactory::NewMethodForNativeFunction(const void *func) { uint32_t numArgs = 2; // function object and this auto method = vm_->GetChunk()->New(nullptr, panda_file::File::EntityId(0)); method->SetNativePointer(const_cast(func)); method->SetNativeBit(true); method->SetNumArgsWithCallField(numArgs); nativeMethods_.push_back(method); return nativeMethods_.back(); } JSMethod *ObjectFactory::NewMethodForAOTFunction(const void *func, size_t numArgs, const JSPandaFile *pf, uint32_t methodId) { auto method = vm_->GetChunk()->New(pf, panda_file::File::EntityId(methodId)); method->SetNativePointer(const_cast(func)); method->SetAotCodeBit(true); method->SetNativeBit(false); method->SetNumArgsWithCallField(numArgs); nativeMethods_.push_back(method); return nativeMethods_.back(); } JSHandle ObjectFactory::NewEcmaDynClassClass(JSHClass *hclass, uint32_t size, JSType type) { NewObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(heap_->AllocateDynClassClass(hclass, classSize)); newClass->Initialize(thread_, size, type, 0); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::InitClassClass() { JSHandle dynClassClassHandle = NewEcmaDynClassClass(nullptr, JSHClass::SIZE, JSType::HCLASS); JSHClass *dynclass = reinterpret_cast(dynClassClassHandle.GetTaggedValue().GetTaggedObject()); dynclass->SetClass(dynclass); return dynClassClassHandle; } // NOLINTNEXTLINE(modernize-avoid-c-arrays) void * ObjectFactory::InternalMethodTable[] = { reinterpret_cast(builtins::BuiltinsGlobal::CallJsBoundFunction), reinterpret_cast(builtins::BuiltinsGlobal::CallJsProxy), reinterpret_cast(builtins::BuiltinsObject::CreateDataPropertyOnObjectFunctions), reinterpret_cast(builtins::BuiltinsCollator::AnonymousCollator), reinterpret_cast(builtins::BuiltinsDateTimeFormat::AnonymousDateTimeFormat), reinterpret_cast(builtins::BuiltinsNumberFormat::NumberFormatInternalFormatNumber), reinterpret_cast(builtins::BuiltinsProxy::InvalidateProxyFunction), reinterpret_cast(builtins::BuiltinsPromiseHandler::AsyncAwaitFulfilled), reinterpret_cast(builtins::BuiltinsPromiseHandler::AsyncAwaitRejected), reinterpret_cast(builtins::BuiltinsPromiseHandler::ResolveElementFunction), reinterpret_cast(builtins::BuiltinsPromiseHandler::Resolve), reinterpret_cast(builtins::BuiltinsPromiseHandler::Reject), reinterpret_cast(builtins::BuiltinsPromiseHandler::Executor) }; void ObjectFactory::GenerateInternalNativeMethods() { size_t length = static_cast(MethodIndex::METHOD_END); for (size_t i = 0; i < length; i++) { uint32_t numArgs = 2; // function object and this auto method = vm_->GetChunk()->New(nullptr, panda_file::File::EntityId(0)); method->SetNativePointer(InternalMethodTable[i]); method->SetNativeBit(true); method->SetNumArgsWithCallField(numArgs); internalNativeMethods_.emplace_back(method); } } JSMethod *ObjectFactory::GetMethodByIndex(MethodIndex idx) { return internalNativeMethods_[static_cast(idx)]; } JSHandle ObjectFactory::NewEcmaDynClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps) { NewObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(heap_->AllocateNonMovableOrHugeObject(hclass, classSize)); newClass->Initialize(thread_, size, type, inlinedProps); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::NewEcmaDynClass(uint32_t size, JSType type, uint32_t inlinedProps) { return NewEcmaDynClass(JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), size, type, inlinedProps); } void ObjectFactory::InitObjectFields(const TaggedObject *object) { auto *klass = object->GetClass(); auto objBodySize = klass->GetObjectSize() - TaggedObject::TaggedObjectSize(); ASSERT(objBodySize % JSTaggedValue::TaggedTypeSize() == 0); uint32_t numOfFields = objBodySize / JSTaggedValue::TaggedTypeSize(); size_t addr = reinterpret_cast(object) + TaggedObject::TaggedObjectSize(); for (uint32_t i = 0; i < numOfFields; i++) { auto *fieldAddr = reinterpret_cast(addr + i * JSTaggedValue::TaggedTypeSize()); *fieldAddr = JSTaggedValue::Undefined().GetRawData(); } } void ObjectFactory::NewJSArrayBufferData(const JSHandle &array, int32_t length) { if (length == 0) { return; } JSTaggedValue data = array->GetArrayBufferData(); if (data != JSTaggedValue::Undefined()) { auto *pointer = JSNativePointer::Cast(data.GetTaggedObject()); auto newData = vm_->GetNativeAreaAllocator()->AllocateBuffer(length * sizeof(uint8_t)); if (memset_s(newData, length, 0, length) != EOK) { LOG_ECMA(FATAL) << "memset_s failed"; UNREACHABLE(); } pointer->ResetExternalPointer(newData); return; } auto newData = vm_->GetNativeAreaAllocator()->AllocateBuffer(length * sizeof(uint8_t)); if (memset_s(newData, length, 0, length) != EOK) { LOG_ECMA(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, vm_->GetNativeAreaAllocator()); array->SetArrayBufferData(thread_, pointer); } void ObjectFactory::NewJSSharedArrayBufferData(const JSHandle &array, int32_t length) { if (length == 0) { return; } void *newData = nullptr; JSSharedMemoryManager::GetInstance()->CreateOrLoad(&newData, length); if (memset_s(newData, length, 0, length) != EOK) { LOG_ECMA(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewJSNativePointer(newData, JSSharedMemoryManager::RemoveSharedMemory, JSSharedMemoryManager::GetInstance()); array->SetArrayBufferData(thread_, pointer); } JSHandle ObjectFactory::NewJSArrayBuffer(int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetArrayBufferFunction()); JSHandle newTarget(constructor); JSHandle arrayBuffer(NewJSObjectByConstructor(constructor, newTarget)); arrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { auto newData = vm_->GetNativeAreaAllocator()->AllocateBuffer(length); if (memset_s(newData, length, 0, length) != EOK) { LOG_ECMA(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, vm_->GetNativeAreaAllocator()); arrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue()); arrayBuffer->ClearBitField(); } return arrayBuffer; } JSHandle ObjectFactory::NewJSArrayBuffer(void *buffer, int32_t length, const DeleteEntryPoint &deleter, void *data, bool share) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetArrayBufferFunction()); JSHandle newTarget(constructor); JSHandle arrayBuffer(NewJSObjectByConstructor(constructor, newTarget)); length = buffer == nullptr ? 0 : length; arrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { JSHandle pointer = NewJSNativePointer(buffer, deleter, data); arrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue()); arrayBuffer->SetShared(share); } return arrayBuffer; } JSHandle ObjectFactory::NewJSDataView(JSHandle buffer, uint32_t offset, uint32_t length) { uint32_t arrayLength = buffer->GetArrayBufferByteLength(); if (arrayLength - offset < length) { THROW_TYPE_ERROR_AND_RETURN(thread_, "offset or length error", JSHandle(thread_, JSTaggedValue::Undefined())); } JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetDataViewFunction()); JSHandle newTarget(constructor); JSHandle arrayBuffer(NewJSObjectByConstructor(constructor, newTarget)); arrayBuffer->SetDataView(thread_, JSTaggedValue::True()); arrayBuffer->SetViewedArrayBuffer(thread_, buffer.GetTaggedValue()); arrayBuffer->SetByteLength(length); arrayBuffer->SetByteOffset(offset); return arrayBuffer; } JSHandle ObjectFactory::NewJSSharedArrayBuffer(int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetSharedArrayBufferFunction()); JSHandle newTarget(constructor); JSHandle sharedArrayBuffer(NewJSObjectByConstructor(constructor, newTarget)); sharedArrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { NewJSSharedArrayBufferData(sharedArrayBuffer, length); sharedArrayBuffer->SetShared(true); } return sharedArrayBuffer; } JSHandle ObjectFactory::NewJSSharedArrayBuffer(void *buffer, int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetSharedArrayBufferFunction()); JSHandle newTarget(constructor); JSHandle sharedArrayBuffer(NewJSObjectByConstructor(constructor, newTarget)); length = buffer == nullptr ? 0 : length; sharedArrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { JSHandle pointer = NewJSNativePointer(buffer, JSSharedMemoryManager::RemoveSharedMemory, JSSharedMemoryManager::GetInstance()); sharedArrayBuffer->SetArrayBufferData(thread_, pointer); sharedArrayBuffer->SetShared(true); } return sharedArrayBuffer; } void ObjectFactory::NewJSRegExpByteCodeData(const JSHandle ®exp, void *buffer, size_t size) { if (buffer == nullptr) { return; } auto newBuffer = vm_->GetNativeAreaAllocator()->AllocateBuffer(size); if (memcpy_s(newBuffer, size, buffer, size) != EOK) { LOG_ECMA(FATAL) << "memcpy_s failed"; UNREACHABLE(); } JSTaggedValue data = regexp->GetByteCodeBuffer(); if (data != JSTaggedValue::Undefined()) { JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject()); native->ResetExternalPointer(newBuffer); return; } JSHandle pointer = NewJSNativePointer(newBuffer, NativeAreaAllocator::FreeBufferFunc, vm_->GetNativeAreaAllocator()); regexp->SetByteCodeBuffer(thread_, pointer.GetTaggedValue()); regexp->SetLength(static_cast(size)); } JSHandle ObjectFactory::NewEcmaDynClass(uint32_t size, JSType type, const JSHandle &prototype) { JSHandle newClass = NewEcmaDynClass(size, type); newClass->SetPrototype(thread_, prototype.GetTaggedValue()); return newClass; } JSHandle ObjectFactory::NewJSObject(const JSHandle &jshclass) { JSHandle obj(thread_, JSObject::Cast(NewDynObject(jshclass))); JSHandle emptyArray = EmptyArray(); obj->InitializeHash(); obj->SetElements(thread_, emptyArray, SKIP_BARRIER); obj->SetProperties(thread_, emptyArray, SKIP_BARRIER); return obj; } JSHandle ObjectFactory::CloneProperties(const JSHandle &old) { uint32_t newLength = old->GetLength(); if (newLength == 0) { return EmptyArray(); } NewObjectHook(); auto klass = old->GetClass(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject(klass, size); JSHandle newArray(thread_, header); newArray->SetLength(newLength); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i); newArray->Set(thread_, i, value); } return newArray; } JSHandle ObjectFactory::CloneObjectLiteral(JSHandle object) { NewObjectHook(); auto klass = JSHandle(thread_, object->GetClass()); JSHandle cloneObject = NewJSObject(klass); JSHandle elements(thread_, object->GetElements()); auto newElements = CloneProperties(elements); cloneObject->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, object->GetProperties()); auto newProperties = CloneProperties(properties); cloneObject->SetProperties(thread_, newProperties.GetTaggedValue()); for (uint32_t i = 0; i < klass->GetInlinedProperties(); i++) { cloneObject->SetPropertyInlinedProps(thread_, i, object->GetPropertyInlinedProps(i)); } return cloneObject; } JSHandle ObjectFactory::CloneArrayLiteral(JSHandle object) { NewObjectHook(); auto klass = JSHandle(thread_, object->GetClass()); JSHandle cloneObject(NewJSObject(klass)); cloneObject->SetArrayLength(thread_, object->GetArrayLength()); JSHandle elements(thread_, object->GetElements()); auto newElements = CopyArray(elements, elements->GetLength(), elements->GetLength()); cloneObject->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, object->GetProperties()); auto newProperties = CopyArray(properties, properties->GetLength(), properties->GetLength()); cloneObject->SetProperties(thread_, newProperties.GetTaggedValue()); for (uint32_t i = 0; i < klass->GetInlinedProperties(); i++) { cloneObject->SetPropertyInlinedProps(thread_, i, object->GetPropertyInlinedProps(i)); } return cloneObject; } JSHandle ObjectFactory::CloneProperties(const JSHandle &old, const JSHandle &env, const JSHandle &obj, const JSHandle &constpool) { uint32_t newLength = old->GetLength(); if (newLength == 0) { return EmptyArray(); } NewObjectHook(); auto klass = old->GetClass(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject(klass, size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); newArray->SetLength(newLength); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i); if (!value.IsJSFunction()) { newArray->Set(thread_, i, value); } else { JSHandle valueHandle(thread_, value); JSHandle newFunc = CloneJSFuction(valueHandle, valueHandle->GetFunctionKind()); newFunc->SetLexicalEnv(thread_, env); newFunc->SetHomeObject(thread_, obj); newFunc->SetConstantPool(thread_, constpool); newArray->Set(thread_, i, newFunc); } } return newArray; } JSHandle ObjectFactory::CloneObjectLiteral(JSHandle object, const JSHandle &env, const JSHandle &constpool, bool canShareHClass) { NewObjectHook(); auto klass = JSHandle(thread_, object->GetClass()); if (!canShareHClass) { klass = JSHClass::Clone(thread_, klass); } JSHandle cloneObject = NewJSObject(klass); JSHandle elements(thread_, object->GetElements()); auto newElements = CloneProperties(elements, env, cloneObject, constpool); cloneObject->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, object->GetProperties()); auto newProperties = CloneProperties(properties, env, cloneObject, constpool); cloneObject->SetProperties(thread_, newProperties.GetTaggedValue()); for (uint32_t i = 0; i < klass->GetInlinedProperties(); i++) { JSTaggedValue value = object->GetPropertyInlinedProps(i); if (!value.IsJSFunction()) { cloneObject->SetPropertyInlinedProps(thread_, i, value); } else { JSHandle valueHandle(thread_, value); JSHandle newFunc = CloneJSFuction(valueHandle, valueHandle->GetFunctionKind()); newFunc->SetLexicalEnv(thread_, env); newFunc->SetHomeObject(thread_, cloneObject); newFunc->SetConstantPool(thread_, constpool); cloneObject->SetPropertyInlinedProps(thread_, i, newFunc.GetTaggedValue()); } } return cloneObject; } JSHandle ObjectFactory::CloneJSFuction(JSHandle obj, FunctionKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle jshclass(thread_, obj->GetJSHClass()); JSHandle cloneFunc = NewJSFunctionByDynClass(obj->GetCallTarget(), jshclass, kind); if (kind == FunctionKind::GENERATOR_FUNCTION) { JSHandle objFun = env->GetObjectFunction(); JSHandle initialGeneratorFuncPrototype = NewJSObjectByConstructor(JSHandle(objFun), objFun); JSObject::SetPrototype(thread_, initialGeneratorFuncPrototype, env->GetGeneratorPrototype()); cloneFunc->SetProtoOrDynClass(thread_, initialGeneratorFuncPrototype); } JSTaggedValue length = obj->GetPropertyInlinedProps(JSFunction::LENGTH_INLINE_PROPERTY_INDEX); cloneFunc->SetPropertyInlinedProps(thread_, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, length); cloneFunc->SetModule(obj->GetModule()); return cloneFunc; } JSHandle ObjectFactory::CloneClassCtor(JSHandle ctor, const JSHandle &lexenv, bool canShareHClass) { NewObjectHook(); JSHandle constpool(thread_, ctor->GetConstantPool()); JSHandle hclass(thread_, ctor->GetClass()); if (!canShareHClass) { hclass = JSHClass::Clone(thread_, hclass); } FunctionKind kind = ctor->GetFunctionKind(); ASSERT_PRINT(kind == FunctionKind::CLASS_CONSTRUCTOR || kind == FunctionKind::DERIVED_CONSTRUCTOR, "cloned function is not class"); JSHandle cloneCtor = NewJSFunctionByDynClass(ctor->GetCallTarget(), hclass, kind); for (uint32_t i = 0; i < hclass->GetInlinedProperties(); i++) { JSTaggedValue value = ctor->GetPropertyInlinedProps(i); if (!value.IsJSFunction()) { cloneCtor->SetPropertyInlinedProps(thread_, i, value); } else { JSHandle valueHandle(thread_, value); JSHandle newFunc = CloneJSFuction(valueHandle, valueHandle->GetFunctionKind()); newFunc->SetLexicalEnv(thread_, lexenv); newFunc->SetHomeObject(thread_, cloneCtor); newFunc->SetConstantPool(thread_, constpool); cloneCtor->SetPropertyInlinedProps(thread_, i, newFunc.GetTaggedValue()); } } JSHandle elements(thread_, ctor->GetElements()); auto newElements = CloneProperties(elements, lexenv, JSHandle(cloneCtor), constpool); cloneCtor->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, ctor->GetProperties()); auto newProperties = CloneProperties(properties, lexenv, JSHandle(cloneCtor), constpool); cloneCtor->SetProperties(thread_, newProperties.GetTaggedValue()); cloneCtor->SetConstantPool(thread_, constpool); return cloneCtor; } JSHandle ObjectFactory::NewNonMovableJSObject(const JSHandle &jshclass) { JSHandle obj(thread_, JSObject::Cast(NewNonMovableDynObject(jshclass, jshclass->GetInlinedProperties()))); obj->InitializeHash(); obj->SetElements(thread_, EmptyArray(), SKIP_BARRIER); obj->SetProperties(thread_, EmptyArray(), SKIP_BARRIER); return obj; } JSHandle ObjectFactory::NewJSPrimitiveRef(const JSHandle &dynKlass, const JSHandle &object) { JSHandle obj = JSHandle::Cast(NewJSObject(dynKlass)); obj->SetValue(thread_, object); return obj; } JSHandle ObjectFactory::NewJSArray() { JSHandle env = vm_->GetGlobalEnv(); JSHandle function = env->GetArrayFunction(); return JSHandle(NewJSObjectByConstructor(JSHandle(function), function)); } JSHandle ObjectFactory::NewJSForinIterator(const JSHandle &obj) { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass(env->GetForinIteratorClass()); JSHandle it = JSHandle::Cast(NewJSObject(dynclass)); it->SetObject(thread_, obj); it->SetVisitedKeys(thread_->GlobalConstants()->GetEmptyTaggedQueue()); it->SetRemainingKeys(thread_->GlobalConstants()->GetEmptyTaggedQueue()); it->ClearBitField(); return it; } JSHandle ObjectFactory::CreateJSRegExpInstanceClass(JSHandle proto) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle regexpDynclass = NewEcmaDynClass(JSRegExp::SIZE, JSType::JS_REG_EXP, proto); uint32_t fieldOrder = 0; JSHandle layoutInfoHandle = CreateLayoutInfo(1); { PropertyAttributes attributes = PropertyAttributes::Default(true, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, 0, globalConst->GetLastIndexString(), attributes); } { regexpDynclass->SetLayout(thread_, layoutInfoHandle); regexpDynclass->SetNumberOfProps(fieldOrder); } return regexpDynclass; } JSHandle ObjectFactory::CreateJSArrayInstanceClass(JSHandle proto) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle arrayDynclass = NewEcmaDynClass(JSArray::SIZE, JSType::JS_ARRAY, proto); uint32_t fieldOrder = 0; ASSERT(JSArray::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(1); { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(true, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, 0, globalConst->GetLengthString(), attributes); } { arrayDynclass->SetLayout(thread_, layoutInfoHandle); arrayDynclass->SetNumberOfProps(fieldOrder); } arrayDynclass->SetIsStableElements(true); arrayDynclass->SetHasConstructor(false); return arrayDynclass; } JSHandle ObjectFactory::CreateJSArguments() { JSHandle env = thread_->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto = env->GetObjectFunctionPrototype(); JSHandle argumentsDynclass = NewEcmaDynClass(JSArguments::SIZE, JSType::JS_ARGUMENTS, proto); uint32_t fieldOrder = 0; ASSERT(JSArguments::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(JSArguments::LENGTH_OF_INLINE_PROPERTIES); { PropertyAttributes attributes = PropertyAttributes::Default(true, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::LENGTH_INLINE_PROPERTY_INDEX, globalConst->GetLengthString(), attributes); } ASSERT(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX == fieldOrder); { PropertyAttributes attributes = PropertyAttributes::Default(true, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::ITERATOR_INLINE_PROPERTY_INDEX, env->GetIteratorSymbol().GetTaggedValue(), attributes); } { ASSERT(JSArguments::CALLER_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); attributes.SetIsInlinedProps(true); attributes.SetIsAccessor(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::CALLER_INLINE_PROPERTY_INDEX, thread_->GlobalConstants()->GetHandledCallerString().GetTaggedValue(), attributes); } { ASSERT(JSArguments::CALLEE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); attributes.SetIsInlinedProps(true); attributes.SetIsAccessor(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::CALLEE_INLINE_PROPERTY_INDEX, thread_->GlobalConstants()->GetHandledCalleeString().GetTaggedValue(), attributes); } { argumentsDynclass->SetLayout(thread_, layoutInfoHandle); argumentsDynclass->SetNumberOfProps(fieldOrder); } argumentsDynclass->SetIsStableElements(true); return argumentsDynclass; } JSHandle ObjectFactory::NewJSArguments() { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetArgumentsClass()); JSHandle obj = JSHandle::Cast(NewJSObject(dynclass)); obj->SetParameterMap(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::GetJSError(const ErrorType &errorType, const char *data) { ASSERT_PRINT(errorType == ErrorType::ERROR || errorType == ErrorType::EVAL_ERROR || errorType == ErrorType::RANGE_ERROR || errorType == ErrorType::REFERENCE_ERROR || errorType == ErrorType::SYNTAX_ERROR || errorType == ErrorType::TYPE_ERROR || errorType == ErrorType::URI_ERROR, "The error type is not in the valid range."); if (data != nullptr) { JSHandle handleMsg = NewFromUtf8(data); return NewJSError(errorType, handleMsg); } JSHandle emptyString(thread_->GlobalConstants()->GetHandledEmptyString()); return NewJSError(errorType, emptyString); } JSHandle ObjectFactory::NewJSError(const ErrorType &errorType, const JSHandle &message) { // if there have exception in thread, then return current exception, no need to new js error. if (thread_->HasPendingException()) { JSHandle obj(thread_, thread_->GetException()); return obj; } // current frame may be entry frame, exception happened in JSFunction::Call and JSFunction::Construct, // in this case sp = the prev frame (interpreter frame). if (!thread_->IsAsmInterpreter()) { FrameHandler frameHandler(thread_); if (frameHandler.IsInterpretedEntryFrame()) { thread_->SetCurrentSPFrame(frameHandler.GetPrevInterpretedFrame()); } } JSHandle env = vm_->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle nativeConstructor; switch (errorType) { case ErrorType::RANGE_ERROR: nativeConstructor = env->GetRangeErrorFunction(); break; case ErrorType::EVAL_ERROR: nativeConstructor = env->GetEvalErrorFunction(); break; case ErrorType::REFERENCE_ERROR: nativeConstructor = env->GetReferenceErrorFunction(); break; case ErrorType::TYPE_ERROR: nativeConstructor = env->GetTypeErrorFunction(); break; case ErrorType::URI_ERROR: nativeConstructor = env->GetURIErrorFunction(); break; case ErrorType::SYNTAX_ERROR: nativeConstructor = env->GetSyntaxErrorFunction(); break; default: nativeConstructor = env->GetErrorFunction(); break; } JSHandle nativeFunc = JSHandle::Cast(nativeConstructor); JSHandle nativePrototype(thread_, nativeFunc->GetFunctionPrototype()); JSHandle ctorKey = globalConst->GetHandledConstructorString(); JSHandle undefined = thread_->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo info = EcmaInterpreter::NewRuntimeCallInfo(thread_, undefined, nativePrototype, undefined, 1); info.SetCallArg(message.GetTaggedValue()); JSTaggedValue obj = JSFunction::Invoke(&info, ctorKey); JSHandle handleNativeInstanceObj(thread_, obj); return handleNativeInstanceObj; } JSHandle ObjectFactory::NewJSObjectByConstructor(const JSHandle &constructor, const JSHandle &newTarget) { JSHandle jshclass; if (!constructor->HasFunctionPrototype() || (constructor->GetProtoOrDynClass().IsHeapObject() && constructor->GetFunctionPrototype().IsECMAObject())) { jshclass = JSFunction::GetInstanceJSHClass(thread_, constructor, newTarget); } else { JSHandle env = vm_->GetGlobalEnv(); jshclass = JSFunction::GetInstanceJSHClass(thread_, JSHandle(env->GetObjectFunction()), newTarget); } // Check this exception elsewhere RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread_); return NewJSObjectWithInit(jshclass); } JSHandle ObjectFactory::NewJSObjectWithInit(const JSHandle &jshclass) { JSHandle obj = NewJSObject(jshclass); InitializeJSObject(obj, jshclass); return obj; } void ObjectFactory::InitializeJSObject(const JSHandle &obj, const JSHandle &jshclass) { JSType type = jshclass->GetObjectType(); switch (type) { case JSType::JS_OBJECT: case JSType::JS_ERROR: case JSType::JS_EVAL_ERROR: case JSType::JS_RANGE_ERROR: case JSType::JS_REFERENCE_ERROR: case JSType::JS_TYPE_ERROR: case JSType::JS_URI_ERROR: case JSType::JS_SYNTAX_ERROR: case JSType::JS_ITERATOR: { break; } case JSType::JS_INTL: { JSIntl::Cast(*obj)->SetFallbackSymbol(thread_, JSTaggedValue::Undefined()); JSHandle jsSymbol = NewPublicSymbolWithChar("IntlLegacyConstructedSymbol"); JSIntl::Cast(*obj)->SetFallbackSymbol(thread_, jsSymbol); break; } case JSType::JS_LOCALE: { JSLocale::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_DATE_TIME_FORMAT: { JSDateTimeFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetCalendar(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetNumberingSystem(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetTimeZone(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetLocaleIcu(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetSimpleDateTimeFormatIcu(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetIso8601(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetBoundFormat(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetHourCycle(HourCycleOption::EXCEPTION); JSDateTimeFormat::Cast(*obj)->SetDateStyle(DateTimeStyleOption::EXCEPTION); JSDateTimeFormat::Cast(*obj)->SetTimeStyle(DateTimeStyleOption::EXCEPTION); break; } case JSType::JS_NUMBER_FORMAT: { JSNumberFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetNumberingSystem(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetCurrency(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetUnit(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMinimumIntegerDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMinimumFractionDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMaximumFractionDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMinimumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMaximumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetUseGrouping(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetBoundFormat(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetStyle(StyleOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetCurrencySign(CurrencySignOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetCurrencyDisplay(CurrencyDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetUnitDisplay(UnitDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetSignDisplay(SignDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetCompactDisplay(CompactDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetNotation(NotationOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetRoundingType(RoundingType::EXCEPTION); break; } case JSType::JS_RELATIVE_TIME_FORMAT: { JSRelativeTimeFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetInitializedRelativeTimeFormat(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetNumberingSystem(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetAvailableLocales(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetStyle(RelativeStyleOption::EXCEPTION); JSRelativeTimeFormat::Cast(*obj)->SetNumeric(NumericOption::EXCEPTION); break; } case JSType::JS_COLLATOR: { JSCollator::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetCollation(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetBoundCompare(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetUsage(UsageOption::EXCEPTION); JSCollator::Cast(*obj)->SetCaseFirst(CaseFirstOption::EXCEPTION); JSCollator::Cast(*obj)->SetSensitivity(SensitivityOption::EXCEPTION); JSCollator::Cast(*obj)->SetIgnorePunctuation(false); JSCollator::Cast(*obj)->SetNumeric(false); break; } case JSType::JS_PLURAL_RULES: { JSPluralRules::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetInitializedPluralRules(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMinimumIntegerDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMinimumFractionDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMaximumFractionDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMinimumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMaximumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetIcuPR(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetIcuNF(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetRoundingType(RoundingType::EXCEPTION); JSPluralRules::Cast(*obj)->SetType(TypeOption::EXCEPTION); break; } case JSType::JS_DISPLAYNAMES: { JSDisplayNames::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSDisplayNames::Cast(*obj)->SetType(TypednsOption::EXCEPTION); JSDisplayNames::Cast(*obj)->SetStyle(StyOption::EXCEPTION); JSDisplayNames::Cast(*obj)->SetFallback(FallbackOption::EXCEPTION); JSDisplayNames::Cast(*obj)->SetIcuLDN(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_LIST_FORMAT: { JSListFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSListFormat::Cast(*obj)->SetType(ListTypeOption::EXCEPTION); JSListFormat::Cast(*obj)->SetStyle(ListStyleOption::EXCEPTION); JSListFormat::Cast(*obj)->SetIcuLF(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_ARRAY: { JSArray::Cast(*obj)->SetLength(thread_, JSTaggedValue(0)); auto accessor = thread_->GlobalConstants()->GetArrayLengthAccessor(); JSArray::Cast(*obj)->SetPropertyInlinedProps(thread_, JSArray::LENGTH_INLINE_PROPERTY_INDEX, accessor); break; } case JSType::JS_DATE: JSDate::Cast(*obj)->SetTimeValue(thread_, JSTaggedValue(0.0)); JSDate::Cast(*obj)->SetLocalOffset(thread_, JSTaggedValue(JSDate::MAX_DOUBLE)); break; case JSType::JS_TYPED_ARRAY: case JSType::JS_INT8_ARRAY: case JSType::JS_UINT8_ARRAY: case JSType::JS_UINT8_CLAMPED_ARRAY: case JSType::JS_INT16_ARRAY: case JSType::JS_UINT16_ARRAY: case JSType::JS_INT32_ARRAY: case JSType::JS_UINT32_ARRAY: case JSType::JS_FLOAT32_ARRAY: case JSType::JS_FLOAT64_ARRAY: case JSType::JS_BIGINT64_ARRAY: case JSType::JS_BIGUINT64_ARRAY: JSTypedArray::Cast(*obj)->SetViewedArrayBuffer(thread_, JSTaggedValue::Undefined()); JSTypedArray::Cast(*obj)->SetTypedArrayName(thread_, JSTaggedValue::Undefined()); JSTypedArray::Cast(*obj)->SetByteLength(0); JSTypedArray::Cast(*obj)->SetByteOffset(0); JSTypedArray::Cast(*obj)->SetArrayLength(0); JSTypedArray::Cast(*obj)->SetContentType(ContentType::None); break; case JSType::JS_REG_EXP: JSRegExp::Cast(*obj)->SetByteCodeBuffer(thread_, JSTaggedValue::Undefined()); JSRegExp::Cast(*obj)->SetOriginalSource(thread_, JSTaggedValue::Undefined()); JSRegExp::Cast(*obj)->SetOriginalFlags(thread_, JSTaggedValue(0)); JSRegExp::Cast(*obj)->SetLength(0); break; case JSType::JS_PRIMITIVE_REF: JSPrimitiveRef::Cast(*obj)->SetValue(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_SET: JSSet::Cast(*obj)->SetLinkedSet(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_MAP: JSMap::Cast(*obj)->SetLinkedMap(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_WEAK_MAP: JSWeakMap::Cast(*obj)->SetLinkedMap(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_WEAK_SET: JSWeakSet::Cast(*obj)->SetLinkedSet(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_WEAK_REF: JSWeakRef::Cast(*obj)->SetWeakObject(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_FINALIZATION_REGISTRY: JSFinalizationRegistry::Cast(*obj)->SetCleanupCallback(thread_, JSTaggedValue::Undefined()); JSFinalizationRegistry::Cast(*obj)->SetNoUnregister(thread_, JSTaggedValue::Undefined()); JSFinalizationRegistry::Cast(*obj)->SetMaybeUnregister(thread_, JSTaggedValue::Undefined()); JSFinalizationRegistry::Cast(*obj)->SetNext(thread_, JSTaggedValue::Null()); JSFinalizationRegistry::Cast(*obj)->SetPrev(thread_, JSTaggedValue::Null()); break; case JSType::JS_GENERATOR_OBJECT: JSGeneratorObject::Cast(*obj)->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); JSGeneratorObject::Cast(*obj)->SetResumeResult(thread_, JSTaggedValue::Undefined()); JSGeneratorObject::Cast(*obj)->SetGeneratorState(JSGeneratorState::UNDEFINED); JSGeneratorObject::Cast(*obj)->SetResumeMode(GeneratorResumeMode::UNDEFINED); break; case JSType::JS_STRING_ITERATOR: JSStringIterator::Cast(*obj)->SetStringIteratorNextIndex(0); JSStringIterator::Cast(*obj)->SetIteratedString(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ARRAY_BUFFER: JSArrayBuffer::Cast(*obj)->SetArrayBufferData(thread_, JSTaggedValue::Undefined()); JSArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0); JSArrayBuffer::Cast(*obj)->ClearBitField(); break; case JSType::JS_SHARED_ARRAY_BUFFER: JSArrayBuffer::Cast(*obj)->SetArrayBufferData(thread_, JSTaggedValue::Undefined()); JSArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0); JSArrayBuffer::Cast(*obj)->SetShared(true); break; case JSType::JS_PROMISE: JSPromise::Cast(*obj)->SetPromiseState(PromiseState::PENDING); JSPromise::Cast(*obj)->SetPromiseResult(thread_, JSTaggedValue::Undefined()); JSPromise::Cast(*obj)->SetPromiseRejectReactions(thread_, GetEmptyTaggedQueue().GetTaggedValue()); JSPromise::Cast(*obj)->SetPromiseFulfillReactions(thread_, GetEmptyTaggedQueue().GetTaggedValue()); JSPromise::Cast(*obj)->SetPromiseIsHandled(false); break; case JSType::JS_DATA_VIEW: JSDataView::Cast(*obj)->SetDataView(thread_, JSTaggedValue(false)); JSDataView::Cast(*obj)->SetViewedArrayBuffer(thread_, JSTaggedValue::Undefined()); JSDataView::Cast(*obj)->SetByteLength(0); JSDataView::Cast(*obj)->SetByteOffset(0); break; // non ECMA standard jsapi container case JSType::JS_API_ARRAY_LIST: JSAPIArrayList::Cast(*obj)->SetLength(thread_, JSTaggedValue(0)); break; case JSType::JS_API_TREE_MAP: JSAPITreeMap::Cast(*obj)->SetTreeMap(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_API_TREE_SET: JSAPITreeSet::Cast(*obj)->SetTreeSet(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_API_QUEUE: JSAPIQueue::Cast(*obj)->SetLength(thread_, JSTaggedValue(0)); JSAPIQueue::Cast(*obj)->SetFront(0); JSAPIQueue::Cast(*obj)->SetTail(0); break; case JSType::JS_API_PLAIN_ARRAY: JSAPIPlainArray::Cast(*obj)->SetLength(0); JSAPIPlainArray::Cast(*obj)->SetValues(thread_, JSTaggedValue(0)); JSAPIPlainArray::Cast(*obj)->SetKeys(thread_, JSTaggedValue(0)); break; case JSType::JS_API_STACK: JSAPIStack::Cast(*obj)->SetTop(0); break; case JSType::JS_API_DEQUE: JSAPIDeque::Cast(*obj)->SetFirst(0); JSAPIDeque::Cast(*obj)->SetLast(0); break; case JSType::JS_API_VECTOR: JSAPIVector::Cast(*obj)->SetLength(0); break; case JSType::JS_API_LIST: JSAPIList::Cast(*obj)->SetSingleList(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_API_LINKED_LIST: JSAPILinkedList::Cast(*obj)->SetDoubleList(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ASYNC_FUNC_OBJECT: JSAsyncFuncObject::Cast(*obj)->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); JSAsyncFuncObject::Cast(*obj)->SetResumeResult(thread_, JSTaggedValue::Undefined()); JSAsyncFuncObject::Cast(*obj)->SetPromise(JSTaggedValue::Undefined()); break; case JSType::JS_FUNCTION: case JSType::JS_GENERATOR_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj), FunctionKind::NORMAL_FUNCTION); break; case JSType::JS_PROXY_REVOC_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj), FunctionKind::NORMAL_FUNCTION); JSProxyRevocFunction::Cast(*obj)->SetRevocableProxy(JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_REACTIONS_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj), FunctionKind::NORMAL_FUNCTION); JSPromiseReactionsFunction::Cast(*obj)->SetPromise(JSTaggedValue::Undefined()); JSPromiseReactionsFunction::Cast(*obj)->SetAlreadyResolved(JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_EXECUTOR_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj), FunctionKind::NORMAL_FUNCTION); JSPromiseExecutorFunction::Cast(*obj)->SetCapability(JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj), FunctionKind::NORMAL_FUNCTION); JSPromiseAllResolveElementFunction::Cast(*obj)->SetIndex(JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetValues(JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetCapabilities(JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetRemainingElements(JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetAlreadyCalled(JSTaggedValue::Undefined()); break; case JSType::JS_INTL_BOUND_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj), FunctionKind::NORMAL_FUNCTION); JSIntlBoundFunction::Cast(*obj)->SetNumberFormat(JSTaggedValue::Undefined()); JSIntlBoundFunction::Cast(*obj)->SetDateTimeFormat(JSTaggedValue::Undefined()); JSIntlBoundFunction::Cast(*obj)->SetCollator(JSTaggedValue::Undefined()); break; case JSType::JS_BOUND_FUNCTION: JSBoundFunction::Cast(*obj)->SetBoundTarget(JSTaggedValue::Undefined()); JSBoundFunction::Cast(*obj)->SetBoundThis(JSTaggedValue::Undefined()); JSBoundFunction::Cast(*obj)->SetBoundArguments(JSTaggedValue::Undefined()); break; case JSType::JS_ARGUMENTS: JSArguments::Cast(*obj)->SetParameterMap(JSTaggedValue::Undefined()); break; case JSType::JS_FORIN_ITERATOR: case JSType::JS_MAP_ITERATOR: case JSType::JS_SET_ITERATOR: case JSType::JS_REG_EXP_ITERATOR: case JSType::JS_API_ARRAYLIST_ITERATOR: case JSType::JS_API_TREEMAP_ITERATOR: case JSType::JS_API_TREESET_ITERATOR: case JSType::JS_API_QUEUE_ITERATOR: case JSType::JS_API_DEQUE_ITERATOR: case JSType::JS_API_STACK_ITERATOR: case JSType::JS_ARRAY_ITERATOR: case JSType::JS_API_PLAIN_ARRAY_ITERATOR: break; case JSType::JS_CJS_MODULE: JSCjsModule::Cast(*obj)->SetId(thread_, JSTaggedValue::Undefined()); JSCjsModule::Cast(*obj)->SetExports(thread_, JSTaggedValue::Undefined()); JSCjsModule::Cast(*obj)->SetPath(thread_, JSTaggedValue::Undefined()); JSCjsModule::Cast(*obj)->SetFilename(thread_, JSTaggedValue::Undefined()); JSCjsModule::Cast(*obj)->SetStatus(CjsModuleStatus::UNLOAD); break; case JSType::JS_CJS_EXPORTS: JSCjsExports::Cast(*obj)->SetExports(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_CJS_REQUIRE: JSCjsRequire::Cast(*obj)->SetCache(thread_, JSTaggedValue::Undefined()); JSCjsRequire::Cast(*obj)->SetParent(thread_, JSTaggedValue::Undefined()); break; default: UNREACHABLE(); } } FreeObject *ObjectFactory::FillFreeObject(uintptr_t address, size_t size, RemoveSlots removeSlots) { FreeObject *object = nullptr; const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); if (size >= FreeObject::SIZE_OFFSET && size < FreeObject::SIZE) { object = reinterpret_cast(address); object->SetClassWithoutBarrier(JSHClass::Cast(globalConst->GetFreeObjectWithOneFieldClass().GetTaggedObject())); object->SetNext(INVALID_OBJECT); } else if (size >= FreeObject::SIZE) { object = reinterpret_cast(address); if (!vm_->IsGlobalConstInitialized()) { object->SetClassWithoutBarrier(nullptr); } else { object->SetClassWithoutBarrier( JSHClass::Cast(globalConst->GetFreeObjectWithTwoFieldClass().GetTaggedObject())); } object->SetAvailable(size); object->SetNext(INVALID_OBJECT); } else if (size == FreeObject::NEXT_OFFSET) { object = reinterpret_cast(address); object->SetClassWithoutBarrier( JSHClass::Cast(globalConst->GetFreeObjectWithNoneFieldClass().GetTaggedObject())); } else { LOG_ECMA(DEBUG) << "Fill free object size is smaller"; } if (removeSlots == RemoveSlots::YES) { Region *region = Region::ObjectAddressToRange(object); if (!region->InYoungSpace()) { heap_->ClearSlotsRange(region, address, address + size); } } return object; } TaggedObject *ObjectFactory::NewDynObject(const JSHandle &dynclass) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject(*dynclass); uint32_t inobjPropCount = dynclass->GetInlinedProperties(); if (inobjPropCount > 0) { InitializeExtraProperties(dynclass, header, inobjPropCount); } return header; } TaggedObject *ObjectFactory::NewNonMovableDynObject(const JSHandle &dynclass, int inobjPropCount) { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject(*dynclass); if (inobjPropCount > 0) { InitializeExtraProperties(dynclass, header, inobjPropCount); } return header; } void ObjectFactory::InitializeExtraProperties(const JSHandle &dynclass, TaggedObject *obj, int inobjPropCount) { ASSERT(inobjPropCount * JSTaggedValue::TaggedTypeSize() < dynclass->GetObjectSize()); auto paddr = reinterpret_cast(obj) + dynclass->GetObjectSize(); JSTaggedType initVal = JSTaggedValue::Undefined().GetRawData(); for (int i = 0; i < inobjPropCount; ++i) { paddr -= JSTaggedValue::TaggedTypeSize(); *reinterpret_cast(paddr) = initVal; } } JSHandle ObjectFactory::OrdinaryNewJSObjectCreate(const JSHandle &proto) { JSHandle protoValue(proto); JSHandle protoDyn = NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, protoValue); JSHandle newObj = NewJSObject(protoDyn); newObj->GetJSHClass()->SetExtensible(true); return newObj; } JSHandle ObjectFactory::NewJSFunction(const JSHandle &env, const void *nativeFunc, FunctionKind kind) { JSMethod *target = NewMethodForNativeFunction(nativeFunc); return NewJSFunction(env, target, kind); } JSHandle ObjectFactory::NewJSFunction(const JSHandle &env, JSMethod *method, FunctionKind kind) { JSHandle dynclass; if (kind == FunctionKind::BASE_CONSTRUCTOR) { dynclass = JSHandle::Cast(env->GetFunctionClassWithProto()); } else if (JSFunction::IsConstructorKind(kind)) { dynclass = JSHandle::Cast(env->GetConstructorFunctionClass()); } else { dynclass = JSHandle::Cast(env->GetNormalFunctionClass()); } return NewJSFunctionByDynClass(method, dynclass, kind); } JSHandle ObjectFactory::CreateFunctionClass(FunctionKind kind, uint32_t size, JSType type, const JSHandle &prototype) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle functionClass = NewEcmaDynClass(size, type, prototype); { functionClass->SetCallable(true); // FunctionKind = BASE_CONSTRUCTOR if (JSFunction::IsConstructorKind(kind)) { functionClass->SetConstructor(true); } functionClass->SetExtensible(true); } uint32_t fieldOrder = 0; ASSERT(JSFunction::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(JSFunction::LENGTH_OF_INLINE_PROPERTIES); { PropertyAttributes attributes = PropertyAttributes::Default(false, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetLengthString(), attributes); fieldOrder++; } ASSERT(JSFunction::NAME_INLINE_PROPERTY_INDEX == fieldOrder); // not set name in-object property on class which may have a name() method if (!JSFunction::IsClassConstructor(kind)) { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, thread_->GlobalConstants()->GetHandledNameString().GetTaggedValue(), attributes); fieldOrder++; } if (JSFunction::HasPrototype(kind) && !JSFunction::IsClassConstructor(kind)) { ASSERT(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(true, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetPrototypeString(), attributes); fieldOrder++; } else if (JSFunction::IsClassConstructor(kind)) { ASSERT(JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetPrototypeString(), attributes); fieldOrder++; } { functionClass->SetLayout(thread_, layoutInfoHandle); functionClass->SetNumberOfProps(fieldOrder); } return functionClass; } JSHandle ObjectFactory::NewJSFunctionByDynClass(JSMethod *method, const JSHandle &clazz, FunctionKind kind) { JSHandle function = JSHandle::Cast(NewJSObject(clazz)); clazz->SetCallable(true); clazz->SetExtensible(true); JSFunction::InitializeJSFunction(thread_, function, kind); function->SetMethod(method); return function; } JSHandle ObjectFactory::NewJSFunctionByDynClass(const void *func, const JSHandle &clazz, FunctionKind kind) { JSHandle function = JSHandle::Cast(NewJSObject(clazz)); clazz->SetCallable(true); clazz->SetExtensible(true); JSFunction::InitializeJSFunction(thread_, function, kind); function->SetMethod(NewMethodForNativeFunction(func)); return function; } JSHandle ObjectFactory::NewJSNativeErrorFunction(const JSHandle &env, const void *nativeFunc) { JSMethod *target = NewMethodForNativeFunction(nativeFunc); JSHandle dynclass = JSHandle::Cast(env->GetNativeErrorFunctionClass()); return NewJSFunctionByDynClass(target, dynclass, FunctionKind::BUILTIN_CONSTRUCTOR); } JSHandle ObjectFactory::NewSpecificTypedArrayFunction(const JSHandle &env, const void *nativeFunc) { JSMethod *target = NewMethodForNativeFunction(nativeFunc); JSHandle dynclass = JSHandle::Cast(env->GetSpecificTypedArrayFunctionClass()); return NewJSFunctionByDynClass(target, dynclass, FunctionKind::BUILTIN_CONSTRUCTOR); } JSHandle ObjectFactory::NewAotFunction(uint32_t numArgs, uintptr_t codeEntry) { JSHandle env = vm_->GetGlobalEnv(); JSMethod *method = NewMethodForNativeFunction(reinterpret_cast(codeEntry)); method->SetAotCodeBit(true); method->SetNativeBit(false); method->SetNumArgsWithCallField(numArgs); JSHandle jsfunc = NewJSFunction(env, method, FunctionKind::NORMAL_FUNCTION); jsfunc->SetCodeEntry(codeEntry); return jsfunc; } JSHandle ObjectFactory::NewJSBoundFunction(const JSHandle &target, const JSHandle &boundThis, const JSHandle &args) { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetFunctionPrototype(); JSHandle dynclass = NewEcmaDynClass(JSBoundFunction::SIZE, JSType::JS_BOUND_FUNCTION, proto); JSHandle bundleFunction = JSHandle::Cast(NewJSObject(dynclass)); bundleFunction->SetBoundTarget(thread_, target); bundleFunction->SetBoundThis(thread_, boundThis); bundleFunction->SetBoundArguments(thread_, args); dynclass->SetCallable(true); if (target.GetTaggedValue().IsConstructor()) { bundleFunction->SetConstructor(true); } JSMethod *method = GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_BOUND_FUNCTION); bundleFunction->SetMethod(method); return bundleFunction; } JSHandle ObjectFactory::NewJSIntlBoundFunction(MethodIndex idx, int functionLength) { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetJSIntlBoundFunctionClass()); JSHandle intlBoundFunc = JSHandle::Cast(NewJSObject(dynclass)); intlBoundFunc->SetNumberFormat(JSTaggedValue::Undefined()); intlBoundFunc->SetDateTimeFormat(JSTaggedValue::Undefined()); intlBoundFunc->SetCollator(JSTaggedValue::Undefined()); intlBoundFunc->SetMethod(GetMethodByIndex(idx)); JSHandle function = JSHandle::Cast(intlBoundFunc); JSFunction::InitializeJSFunction(thread_, function, FunctionKind::NORMAL_FUNCTION); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(functionLength)); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle emptyString = globalConst->GetHandledEmptyString(); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread_, emptyString, false, false, true); JSTaggedValue::DefinePropertyOrThrow(thread_, JSHandle::Cast(function), nameKey, nameDesc); return intlBoundFunc; } JSHandle ObjectFactory::NewJSProxyRevocFunction(const JSHandle &proxy) { JSHandle env = vm_->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynclass = JSHandle::Cast(env->GetProxyRevocFunctionClass()); JSHandle revocFunction = JSHandle::Cast(NewJSObject(dynclass)); revocFunction->SetRevocableProxy(JSTaggedValue::Undefined()); revocFunction->SetRevocableProxy(thread_, proxy); revocFunction->SetMethod(GetMethodByIndex(MethodIndex::BUILTINS_PROXY_INVALIDATE_PROXY_FUNCTION)); JSHandle function = JSHandle::Cast(revocFunction); JSFunction::InitializeJSFunction(thread_, function, FunctionKind::NORMAL_FUNCTION); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(0)); JSHandle emptyString = globalConst->GetHandledEmptyString(); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread_, emptyString, false, false, true); JSTaggedValue::DefinePropertyOrThrow(thread_, JSHandle::Cast(function), nameKey, nameDesc); return revocFunction; } JSHandle ObjectFactory::NewJSAsyncAwaitStatusFunction(MethodIndex idx) { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetAsyncAwaitStatusFunctionClass()); JSHandle awaitFunction = JSHandle::Cast(NewJSObject(dynclass)); awaitFunction->SetAsyncContext(JSTaggedValue::Undefined()); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(awaitFunction)); awaitFunction->SetMethod(GetMethodByIndex(idx)); return awaitFunction; } JSHandle ObjectFactory::NewJSGeneratorFunction(JSMethod *method) { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetGeneratorFunctionClass()); JSHandle generatorFunc = JSHandle::Cast(NewJSObject(dynclass)); JSFunction::InitializeJSFunction(thread_, generatorFunc, FunctionKind::GENERATOR_FUNCTION); generatorFunc->SetMethod(method); return generatorFunc; } JSHandle ObjectFactory::NewJSGeneratorObject(JSHandle generatorFunction) { JSHandle proto(thread_, JSHandle::Cast(generatorFunction)->GetProtoOrDynClass()); if (!proto->IsECMAObject()) { JSHandle realmHandle = JSObject::GetFunctionRealm(thread_, generatorFunction); proto = realmHandle->GetGeneratorPrototype(); } JSHandle dynclass = NewEcmaDynClass(JSGeneratorObject::SIZE, JSType::JS_GENERATOR_OBJECT, proto); JSHandle generatorObject = JSHandle::Cast(NewJSObject(dynclass)); generatorObject->SetGeneratorContext(JSTaggedValue::Undefined()); generatorObject->SetResumeResult(JSTaggedValue::Undefined()); return generatorObject; } JSHandle ObjectFactory::NewAsyncFunction(JSMethod *method) { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetAsyncFunctionClass()); JSHandle asyncFunction = JSHandle::Cast(NewJSObject(dynclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(asyncFunction)); asyncFunction->SetMethod(method); return asyncFunction; } JSHandle ObjectFactory::NewJSAsyncFuncObject() { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetInitialGenerator(); JSHandle dynclass = NewEcmaDynClass(JSAsyncFuncObject::SIZE, JSType::JS_ASYNC_FUNC_OBJECT, proto); JSHandle asyncFuncObject = JSHandle::Cast(NewJSObjectWithInit(dynclass)); return asyncFuncObject; } JSHandle ObjectFactory::NewCompletionRecord(CompletionRecordType type, JSHandle value) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCompletionRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetType(type); obj->SetValue(thread_, value); return obj; } JSHandle ObjectFactory::NewGeneratorContext() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetGeneratorContextClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetRegsArray(thread_, JSTaggedValue::Undefined()); obj->SetMethod(thread_, JSTaggedValue::Undefined()); obj->SetAcc(thread_, JSTaggedValue::Undefined()); obj->SetGeneratorObject(thread_, JSTaggedValue::Undefined()); obj->SetLexicalEnv(thread_, JSTaggedValue::Undefined()); obj->SetNRegs(0); obj->SetBCOffset(0); return obj; } JSHandle ObjectFactory::NewJSPrimitiveRef(const JSHandle &function, const JSHandle &object) { JSHandle obj(NewJSObjectByConstructor(function, JSHandle(function))); obj->SetValue(thread_, object); JSHandle env = vm_->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); if (function.GetTaggedValue() == env->GetStringFunction().GetTaggedValue()) { JSHandle lengthStr = globalConst->GetHandledLengthString(); uint32_t length = EcmaString::Cast(object.GetTaggedValue().GetTaggedObject())->GetLength(); PropertyDescriptor desc(thread_, JSHandle(thread_, JSTaggedValue(length)), false, false, false); JSTaggedValue::DefinePropertyOrThrow(thread_, JSHandle(obj), lengthStr, desc); } return obj; } JSHandle ObjectFactory::NewJSPrimitiveRef(PrimitiveType type, const JSHandle &object) { ObjectFactory *factory = vm_->GetFactory(); JSHandle env = vm_->GetGlobalEnv(); JSHandle function; switch (type) { case PrimitiveType::PRIMITIVE_NUMBER: function = env->GetNumberFunction(); break; case PrimitiveType::PRIMITIVE_STRING: function = env->GetStringFunction(); break; case PrimitiveType::PRIMITIVE_SYMBOL: function = env->GetSymbolFunction(); break; case PrimitiveType::PRIMITIVE_BOOLEAN: function = env->GetBooleanFunction(); break; case PrimitiveType::PRIMITIVE_BIGINT: function = env->GetBigIntFunction(); break; default: break; } JSHandle funcHandle(function); return factory->NewJSPrimitiveRef(funcHandle, object); } JSHandle ObjectFactory::NewJSString(const JSHandle &str) { JSHandle env = vm_->GetGlobalEnv(); JSHandle stringFunc = env->GetStringFunction(); JSHandle obj = JSHandle::Cast(NewJSObjectByConstructor(JSHandle(stringFunc), stringFunc)); obj->SetValue(thread_, str); return obj; } JSHandle ObjectFactory::NewGlobalEnv(JSHClass *globalEnvClass) { NewObjectHook(); // Note: Global env must be allocated in non-movable heap, since its getters will directly return // the offsets of the properties as the address of Handles. TaggedObject *header = heap_->AllocateNonMovableOrHugeObject(globalEnvClass); InitObjectFields(header); return JSHandle(thread_, GlobalEnv::Cast(header)); } JSHandle ObjectFactory::NewLexicalEnv(int numSlots) { NewObjectHook(); size_t size = LexicalEnv::ComputeSize(numSlots); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetEnvClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Hole(), numSlots + LexicalEnv::RESERVED_ENV_LENGTH); return array; } JSHandle ObjectFactory::NewJSSymbol() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetDescription(thread_, JSTaggedValue::Undefined()); obj->SetFlags(0); obj->SetHashField(SymbolTable::Hash(obj.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewPrivateSymbol() { JSHandle obj = NewJSSymbol(); obj->SetPrivate(); return obj; } JSHandle ObjectFactory::NewPrivateNameSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetFlags(0); obj->SetPrivateNameSymbol(); obj->SetDescription(thread_, name); obj->SetHashField(SymbolTable::Hash(name.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewWellKnownSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetFlags(0); obj->SetWellKnownSymbol(); obj->SetDescription(thread_, name); obj->SetHashField(SymbolTable::Hash(name.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewPublicSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetFlags(0); obj->SetDescription(thread_, name); obj->SetHashField(SymbolTable::Hash(name.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewSymbolWithTable(const JSHandle &name) { JSHandle env = vm_->GetGlobalEnv(); JSHandle tableHandle(env->GetRegisterSymbols()); if (tableHandle->ContainsKey(name.GetTaggedValue())) { JSTaggedValue objValue = tableHandle->GetSymbol(name.GetTaggedValue()); return JSHandle(thread_, objValue); } JSHandle obj = NewPublicSymbol(name); JSHandle valueHandle(obj); JSHandle keyHandle(name); JSHandle table = SymbolTable::Insert(thread_, tableHandle, keyHandle, valueHandle); env->SetRegisterSymbols(thread_, table); return obj; } JSHandle ObjectFactory::NewPrivateNameSymbolWithChar(const char *description) { JSHandle string = NewFromUtf8(description); return NewPrivateNameSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewWellKnownSymbolWithChar(const char *description) { JSHandle string = NewFromUtf8(description); return NewWellKnownSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewPublicSymbolWithChar(const char *description) { JSHandle string = NewFromUtf8(description); return NewPublicSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewSymbolWithTableWithChar(const char *description) { JSHandle string = NewFromUtf8(description); return NewSymbolWithTable(JSHandle(string)); } JSHandle ObjectFactory::NewAccessorData() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetAccessorDataClass().GetTaggedObject())); JSHandle acc(thread_, AccessorData::Cast(header)); acc->SetGetter(thread_, JSTaggedValue::Undefined()); acc->SetSetter(thread_, JSTaggedValue::Undefined()); return acc; } JSHandle ObjectFactory::NewInternalAccessor(void *setter, void *getter) { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetInternalAccessorClass().GetTaggedObject())); JSHandle obj(thread_, AccessorData::Cast(header)); obj->SetGetter(thread_, JSTaggedValue::Undefined()); obj->SetSetter(thread_, JSTaggedValue::Undefined()); if (setter != nullptr) { JSHandle setFunc = NewJSNativePointer(setter, nullptr, nullptr, true); obj->SetSetter(thread_, setFunc.GetTaggedValue()); } else { JSTaggedValue setFunc = JSTaggedValue::Undefined(); obj->SetSetter(thread_, setFunc); ASSERT(!obj->HasSetter()); } JSHandle getFunc = NewJSNativePointer(getter, nullptr, nullptr, true); obj->SetGetter(thread_, getFunc); return obj; } JSHandle ObjectFactory::NewPromiseCapability() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCapabilityRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetPromise(thread_, JSTaggedValue::Undefined()); obj->SetResolve(thread_, JSTaggedValue::Undefined()); obj->SetReject(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::NewPromiseReaction() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetReactionsRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetPromiseCapability(thread_, JSTaggedValue::Undefined()); obj->SetHandler(thread_, JSTaggedValue::Undefined()); obj->SetType(PromiseType::RESOLVE); return obj; } JSHandle ObjectFactory::NewPromiseIteratorRecord(const JSHandle &itor, bool done) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPromiseIteratorRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetIterator(thread_, itor.GetTaggedValue()); obj->SetDone(done); return obj; } JSHandle ObjectFactory::NewMicroJobQueue() { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMicroJobQueueClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetPromiseJobQueue(thread_, GetEmptyTaggedQueue().GetTaggedValue()); obj->SetScriptJobQueue(thread_, GetEmptyTaggedQueue().GetTaggedValue()); return obj; } JSHandle ObjectFactory::NewPendingJob(const JSHandle &func, const JSHandle &argv) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPendingJobClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetJob(thread_, func.GetTaggedValue()); obj->SetArguments(thread_, argv.GetTaggedValue()); return obj; } JSHandle ObjectFactory::NewJSProxy(const JSHandle &target, const JSHandle &handler) { NewObjectHook(); TaggedObject *header = nullptr; const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); if (target->IsCallable()) { auto jsProxyCallableClass = JSHClass::Cast(globalConst->GetJSProxyCallableClass().GetTaggedObject()); auto jsProxyConstructClass = JSHClass::Cast(globalConst->GetJSProxyConstructClass().GetTaggedObject()); header = target->IsConstructor() ? heap_->AllocateYoungOrHugeObject(jsProxyConstructClass) : heap_->AllocateYoungOrHugeObject(jsProxyCallableClass); } else { header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetJSProxyOrdinaryClass().GetTaggedObject())); } JSHandle proxy(thread_, header); JSMethod *method = GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_PROXY); proxy->SetMethod(method); proxy->SetTarget(thread_, target.GetTaggedValue()); proxy->SetHandler(thread_, handler.GetTaggedValue()); return proxy; } JSHandle ObjectFactory::NewJSRealm() { JSHandle dynClassClassHandle = NewEcmaDynClassClass(nullptr, JSHClass::SIZE, JSType::HCLASS); JSHClass *dynclass = reinterpret_cast(dynClassClassHandle.GetTaggedValue().GetTaggedObject()); dynclass->SetClass(dynclass); JSHandle realmEnvClass = NewEcmaDynClass(*dynClassClassHandle, GlobalEnv::SIZE, JSType::GLOBAL_ENV); JSHandle realmEnvHandle = NewGlobalEnv(*realmEnvClass); auto result = TemplateMap::Create(thread_); realmEnvHandle->SetTemplateMap(thread_, result); Builtins builtins; builtins.Initialize(realmEnvHandle, thread_); JSHandle protoValue = thread_->GlobalConstants()->GetHandledJSRealmClass(); JSHandle dynHandle = NewEcmaDynClass(JSRealm::SIZE, JSType::JS_REALM, protoValue); JSHandle realm(NewJSObject(dynHandle)); realm->SetGlobalEnv(thread_, realmEnvHandle.GetTaggedValue()); realm->SetValue(JSTaggedValue::Undefined()); JSHandle realmObj = realmEnvHandle->GetJSGlobalObject(); JSHandle realmkey(thread_->GlobalConstants()->GetHandledGlobalString()); PropertyDescriptor realmDesc(thread_, JSHandle::Cast(realmObj), true, false, true); [[maybe_unused]] bool status = JSObject::DefineOwnProperty(thread_, JSHandle::Cast(realm), realmkey, realmDesc); ASSERT_PRINT(status == true, "Realm defineOwnProperty failed"); return realm; } JSHandle ObjectFactory::NewEmptyArray() { NewObjectHook(); auto header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), TaggedArray::SIZE); JSHandle array(thread_, header); array->SetLength(0); return array; } JSHandle ObjectFactory::NewTaggedArray(uint32_t length, JSTaggedValue initVal, bool nonMovable) { if (nonMovable) { return NewTaggedArray(length, initVal, MemSpaceType::NON_MOVABLE); } return NewTaggedArray(length, initVal, MemSpaceType::SEMI_SPACE); } JSHandle ObjectFactory::NewTaggedArray(uint32_t length, JSTaggedValue initVal, MemSpaceType spaceType) { NewObjectHook(); if (length == 0) { return EmptyArray(); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); TaggedObject *header = nullptr; JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); switch (spaceType) { case MemSpaceType::SEMI_SPACE: header = heap_->AllocateYoungOrHugeObject(arrayClass, size); break; case MemSpaceType::OLD_SPACE: header = heap_->AllocateOldOrHugeObject(arrayClass, size); break; case MemSpaceType::NON_MOVABLE: header = heap_->AllocateNonMovableOrHugeObject(arrayClass, size); break; default: UNREACHABLE(); } JSHandle array(thread_, header); array->InitializeWithSpecialValue(initVal, length); return array; } JSHandle ObjectFactory::NewTaggedArray(uint32_t length, JSTaggedValue initVal) { NewObjectHook(); if (length == 0) { return EmptyArray(); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(initVal, length); return array; } JSHandle ObjectFactory::NewDictionaryArray(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetDictionaryClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); return array; } JSHandle ObjectFactory::ExtendArray(const JSHandle &old, uint32_t length, JSTaggedValue initVal) { ASSERT(length > old->GetLength()); NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->SetLength(length); uint32_t oldLength = old->GetLength(); for (uint32_t i = 0; i < oldLength; i++) { JSTaggedValue value = old->Get(i); newArray->Set(thread_, i, value); } for (uint32_t i = oldLength; i < length; i++) { newArray->Set(thread_, i, initVal); } return newArray; } JSHandle ObjectFactory::CopyPartArray(const JSHandle &old, uint32_t start, uint32_t end) { ASSERT(start <= end); ASSERT(end <= old->GetLength()); uint32_t newLength = end - start; if (newLength == 0) { return EmptyArray(); } NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); newArray->SetLength(newLength); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i + start); if (value.IsHole()) { break; } newArray->Set(thread_, i, value); } return newArray; } JSHandle ObjectFactory::CopyArray(const JSHandle &old, [[maybe_unused]] uint32_t oldLength, uint32_t newLength, JSTaggedValue initVal) { if (newLength == 0) { return EmptyArray(); } if (newLength > oldLength) { return ExtendArray(old, newLength, initVal); } NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); newArray->SetLength(newLength); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i); newArray->Set(thread_, i, value); } return newArray; } JSHandle ObjectFactory::CreateLayoutInfo(int properties, JSTaggedValue initVal) { uint32_t arrayLength = LayoutInfo::ComputeArrayLength(LayoutInfo::ComputeGrowCapacity(properties)); JSHandle layoutInfoHandle = JSHandle::Cast(NewTaggedArray(arrayLength, initVal)); layoutInfoHandle->SetNumberOfElements(thread_, 0); return layoutInfoHandle; } JSHandle ObjectFactory::ExtendLayoutInfo(const JSHandle &old, int properties, JSTaggedValue initVal) { ASSERT(properties > old->NumberOfElements()); uint32_t arrayLength = LayoutInfo::ComputeArrayLength(LayoutInfo::ComputeGrowCapacity(properties)); return JSHandle(ExtendArray(JSHandle(old), arrayLength, initVal)); } JSHandle ObjectFactory::CopyLayoutInfo(const JSHandle &old) { uint32_t newLength = old->GetLength(); return JSHandle(CopyArray(JSHandle::Cast(old), newLength, newLength)); } JSHandle ObjectFactory::CopyAndReSort(const JSHandle &old, int end, int capacity) { ASSERT(capacity >= end); JSHandle newArr = CreateLayoutInfo(capacity); Span sp(old->GetProperties(), end); int i = 0; for (; i < end; i++) { newArr->AddKey(thread_, i, sp[i].key_, PropertyAttributes(sp[i].attr_)); } return newArr; } JSHandle ObjectFactory::NewConstantPool(uint32_t capacity) { NewObjectHook(); if (capacity == 0) { return JSHandle::Cast(EmptyArray()); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), capacity); auto header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), capacity); return array; } JSHandle ObjectFactory::NewProgram() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProgramClass().GetTaggedObject())); JSHandle p(thread_, header); p->SetMainFunction(thread_, JSTaggedValue::Undefined()); return p; } JSHandle ObjectFactory::NewModuleNamespace() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetModuleNamespaceClass()); JSHandle obj = NewJSObject(dynclass); JSHandle moduleNamespace = JSHandle::Cast(obj); moduleNamespace->SetModule(thread_, JSTaggedValue::Undefined()); moduleNamespace->SetExports(thread_, JSTaggedValue::Undefined()); return moduleNamespace; } JSHandle ObjectFactory::NewCjsModule() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle moduleObj(env->GetCjsModuleFunction()); JSHandle cjsModule = JSHandle(NewJSObjectByConstructor(JSHandle(moduleObj), moduleObj)); return cjsModule; } JSHandle ObjectFactory::NewCjsExports() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle exportsObj(env->GetCjsExportsFunction()); JSHandle cjsExports = JSHandle(NewJSObjectByConstructor(JSHandle(exportsObj), exportsObj)); return cjsExports; } JSHandle ObjectFactory::NewCjsRequire() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle requireObj(env->GetCjsRequireFunction()); JSHandle cjsRequire = JSHandle(NewJSObjectByConstructor(JSHandle(requireObj), requireObj)); return cjsRequire; } JSHandle ObjectFactory::GetEmptyString() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyString()); } JSHandle ObjectFactory::EmptyArray() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyArray()); } JSHandle ObjectFactory::GetStringFromStringTable(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress) const { NewObjectHook(); if (utf8Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(utf8Data, utf8Len, canBeCompress)); } JSHandle ObjectFactory::GetStringFromStringTableNonMovable(const uint8_t *utf8Data, uint32_t utf8Len) const { NewObjectHook(); if (utf8Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->CreateAndInternStringNonMovable(utf8Data, utf8Len)); } JSHandle ObjectFactory::GetStringFromStringTable(const uint16_t *utf16Data, uint32_t utf16Len, bool canBeCompress) const { NewObjectHook(); if (utf16Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(utf16Data, utf16Len, canBeCompress)); } JSHandle ObjectFactory::GetStringFromStringTable(EcmaString *string) const { ASSERT(string != nullptr); if (string->GetLength() == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(string)); } // NB! don't do special case for C0 80, it means '\u0000', so don't convert to UTF-8 EcmaString *ObjectFactory::GetRawStringFromStringTable(const uint8_t *mutf8Data, uint32_t utf16Len, bool canBeCompressed) const { NewObjectHook(); if (UNLIKELY(utf16Len == 0)) { return *GetEmptyString(); } if (canBeCompressed) { return EcmaString::Cast(vm_->GetEcmaStringTable()->GetOrInternString(mutf8Data, utf16Len, true)); } CVector utf16Data(utf16Len); auto len = utf::ConvertRegionMUtf8ToUtf16(mutf8Data, utf16Data.data(), utf::Mutf8Size(mutf8Data), utf16Len, 0); return EcmaString::Cast(vm_->GetEcmaStringTable()->GetOrInternString(utf16Data.data(), len, false)); } JSHandle ObjectFactory::NewPropertyBox(const JSHandle &value) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPropertyBoxClass().GetTaggedObject())); JSHandle box(thread_, header); box->SetValue(thread_, value); return box; } JSHandle ObjectFactory::NewProtoChangeMarker() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProtoChangeMarkerClass().GetTaggedObject())); JSHandle marker(thread_, header); marker->ClearBitField(); return marker; } JSHandle ObjectFactory::NewProtoChangeDetails() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProtoChangeDetailsClass().GetTaggedObject())); JSHandle protoInfo(thread_, header); protoInfo->SetChangeListener(thread_, JSTaggedValue::Undefined()); protoInfo->SetRegisterIndex(ProtoChangeDetails::UNREGISTERED); return protoInfo; } JSHandle ObjectFactory::NewProfileTypeInfo(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); return array; } JSHandle ObjectFactory::NewBigInt() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetBigIntClass().GetTaggedObject())); JSHandle obj(thread_, BigInt::Cast(header)); obj->SetData(thread_, JSTaggedValue::Undefined()); obj->SetSign(false); return obj; } // static void ObjectFactory::NewObjectHook() const { #ifndef NDEBUG if (vm_->GetJSOptions().EnableForceGC() && vm_->IsInitialized()) { if (vm_->GetJSOptions().ForceFullGC()) { vm_->CollectGarbage(TriggerGCType::YOUNG_GC); vm_->CollectGarbage(TriggerGCType::OLD_GC); vm_->CollectGarbage(TriggerGCType::FULL_GC); } else { vm_->CollectGarbage(TriggerGCType::YOUNG_GC); vm_->CollectGarbage(TriggerGCType::OLD_GC); } } #endif } JSHandle ObjectFactory::NewTaggedQueue(uint32_t length) { uint32_t queueLength = TaggedQueue::QueueToArrayIndex(length); auto queue = JSHandle::Cast(NewTaggedArray(queueLength, JSTaggedValue::Hole())); queue->SetStart(thread_, JSTaggedValue(0)); // equal to 0 when add 1. queue->SetEnd(thread_, JSTaggedValue(0)); queue->SetCapacity(thread_, JSTaggedValue(length)); return queue; } JSHandle ObjectFactory::GetEmptyTaggedQueue() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyTaggedQueue()); } JSHandle ObjectFactory::NewJSSetIterator(const JSHandle &set, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetSetIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSSetIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedSet(thread_, set->GetLinkedSet()); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSRegExpIterator(const JSHandle &matcher, const JSHandle &inputStr, bool global, bool fullUnicode) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetRegExpIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSRegExpIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratingRegExp(thread_, matcher.GetTaggedValue()); iter->SetIteratedString(thread_, inputStr.GetTaggedValue()); iter->SetGlobal(global); iter->SetUnicode(fullUnicode); iter->SetDone(false); return iter; } JSHandle ObjectFactory::NewJSMapIterator(const JSHandle &map, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetMapIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSMapIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedMap(thread_, map->GetLinkedMap()); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSArrayIterator(const JSHandle &array, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetArrayIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSArrayIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedArray(thread_, array); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::CreateJSPromiseReactionsFunction(MethodIndex idx) { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetPromiseReactionFunctionClass()); JSHandle reactionsFunction = JSHandle::Cast(NewJSObject(dynclass)); reactionsFunction->SetPromise(thread_, JSTaggedValue::Hole()); reactionsFunction->SetAlreadyResolved(thread_, JSTaggedValue::Hole()); reactionsFunction->SetMethod(GetMethodByIndex(idx)); JSHandle function = JSHandle::Cast(reactionsFunction); JSFunction::InitializeJSFunction(thread_, function); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(1)); return reactionsFunction; } JSHandle ObjectFactory::CreateJSPromiseExecutorFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetPromiseExecutorFunctionClass()); JSHandle executorFunction = JSHandle::Cast(NewJSObject(dynclass)); executorFunction->SetCapability(thread_, JSTaggedValue::Hole()); executorFunction->SetMethod(GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_EXECUTOR)); executorFunction->SetCapability(thread_, JSTaggedValue::Undefined()); JSHandle function = JSHandle::Cast(executorFunction); JSFunction::InitializeJSFunction(thread_, function, FunctionKind::NORMAL_FUNCTION); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(FunctionLength::TWO)); return executorFunction; } JSHandle ObjectFactory::NewJSPromiseAllResolveElementFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle dynclass = JSHandle::Cast(env->GetPromiseAllResolveElementFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(dynclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_RESOLVE_ELEMENT_FUNCTION)); function->SetIndex(JSTaggedValue::Undefined()); function->SetValues(JSTaggedValue::Undefined()); function->SetCapabilities(JSTaggedValue::Undefined()); function->SetRemainingElements(JSTaggedValue::Undefined()); function->SetAlreadyCalled(JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } EcmaString *ObjectFactory::InternString(const JSHandle &key) { EcmaString *str = EcmaString::Cast(key->GetTaggedObject()); if (str->IsInternString()) { return str; } EcmaStringTable *stringTable = vm_->GetEcmaStringTable(); return stringTable->GetOrInternString(str); } JSHandle ObjectFactory::NewTransitionHandler() { NewObjectHook(); TransitionHandler *handler = TransitionHandler::Cast(heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTransitionHandlerClass().GetTaggedObject()))); handler->SetHandlerInfo(JSTaggedValue::Undefined()); handler->SetTransitionHClass(JSTaggedValue::Undefined()); return JSHandle(thread_, handler); } JSHandle ObjectFactory::NewPrototypeHandler() { NewObjectHook(); PrototypeHandler *header = PrototypeHandler::Cast(heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPrototypeHandlerClass().GetTaggedObject()))); JSHandle handler(thread_, header); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetProtoCell(thread_, JSTaggedValue::Undefined()); handler->SetHolder(thread_, JSTaggedValue::Undefined()); return handler; } JSHandle ObjectFactory::NewPromiseRecord() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPromiseRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetValue(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::NewResolvingFunctionsRecord() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPromiseResolvingFunctionsRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetResolveFunction(thread_, JSTaggedValue::Undefined()); obj->SetRejectFunction(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::CreateObjectClass(const JSHandle &properties, size_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetObjectFunctionPrototype(); uint32_t fieldOrder = 0; JSMutableHandle key(thread_, JSTaggedValue::Undefined()); JSHandle layoutInfoHandle = CreateLayoutInfo(length); while (fieldOrder < length) { key.Update(properties->Get(fieldOrder * 2)); // 2: Meaning to double ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); PropertyAttributes attributes = PropertyAttributes::Default(); if (properties->Get(fieldOrder * 2 + 1).IsAccessor()) { // 2: Meaning to double attributes.SetIsAccessor(true); } attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, key.GetTaggedValue(), attributes); fieldOrder++; } ASSERT(fieldOrder <= PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES); JSHandle objClass = NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, fieldOrder); objClass->SetPrototype(thread_, proto.GetTaggedValue()); { objClass->SetExtensible(true); objClass->SetIsLiteral(true); objClass->SetLayout(thread_, layoutInfoHandle); objClass->SetNumberOfProps(fieldOrder); } return objClass; } JSHandle ObjectFactory::SetLayoutInObjHClass(const JSHandle &properties, size_t length, const JSHandle &objClass) { JSMutableHandle key(thread_, JSTaggedValue::Undefined()); JSHandle newObjHclass(objClass); for (size_t fieldOffset = 0; fieldOffset < length; fieldOffset++) { key.Update(properties->Get(fieldOffset * 2)); // 2 : pair of key and value ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); PropertyAttributes attributes = PropertyAttributes::Default(); if (properties->Get(fieldOffset * 2 + 1).IsAccessor()) { // 2: Meaning to double attributes.SetIsAccessor(true); } attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::MIXED); attributes.SetOffset(fieldOffset); newObjHclass = JSHClass::SetPropertyOfObjHClass(thread_, newObjHclass, key, attributes); } return newObjHclass; } JSHandle ObjectFactory::GetObjectLiteralHClass(const JSHandle &properties, size_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetObjectFunctionPrototype(); // 64 : If object literal gets too many properties, create hclass directly. const int HCLASS_CACHE_SIZE = 64; if (length >= HCLASS_CACHE_SIZE) { return CreateObjectClass(properties, length); } JSHandle maybeCache = env->GetObjectLiteralHClassCache(); if (maybeCache->IsHole()) { JSHandle cacheArr = NewTaggedArray(HCLASS_CACHE_SIZE); env->SetObjectLiteralHClassCache(thread_, cacheArr.GetTaggedValue()); } JSHandle hclassCache = env->GetObjectLiteralHClassCache(); JSHandle hclassCacheArr = JSHandle::Cast(hclassCache); JSTaggedValue maybeHClass = hclassCacheArr->Get(length); if (maybeHClass.IsHole()) { JSHandle objHClass = NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, length); objHClass->SetPrototype(thread_, proto.GetTaggedValue()); { objHClass->SetNumberOfProps(0); objHClass->SetExtensible(true); objHClass->SetIsLiteral(true); } hclassCacheArr->Set(thread_, length, objHClass); return SetLayoutInObjHClass(properties, length, objHClass); } return SetLayoutInObjHClass(properties, length, JSHandle(thread_, maybeHClass)); } JSHandle ObjectFactory::GetObjectLiteralByHClass(const JSHandle &properties, size_t length) { JSHandle dynclass = GetObjectLiteralHClass(properties, length); JSHandle obj = NewJSObjectWithInit(dynclass); return obj; } JSHandle ObjectFactory::NewEmptyJSObject() { JSHandle env = vm_->GetGlobalEnv(); JSHandle builtinObj = env->GetObjectFunction(); return NewJSObjectByConstructor(JSHandle(builtinObj), builtinObj); } uintptr_t ObjectFactory::NewSpaceBySnapshotAllocator(size_t size) { NewObjectHook(); return heap_->AllocateSnapshotSpace(size); } JSHandle ObjectFactory::NewMachineCodeObject(size_t length, const uint8_t *data) { NewObjectHook(); TaggedObject *obj = heap_->AllocateMachineCodeObject(JSHClass::Cast( thread_->GlobalConstants()->GetMachineCodeClass().GetTaggedObject()), length + MachineCode::SIZE); MachineCode *code = MachineCode::Cast(obj); if (code == nullptr) { LOG_ECMA(FATAL) << "machine code cast failed"; UNREACHABLE(); } code->SetInstructionSizeInBytes(static_cast(length)); if (data != nullptr) { code->SetData(data, length); } JSHandle codeObj(thread_, code); return codeObj; } JSHandle ObjectFactory::NewClassInfoExtractor(JSMethod *ctorMethod) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetClassInfoExtractorHClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->ClearBitField(); obj->SetConstructorMethod(ctorMethod); JSHandle emptyArray = EmptyArray(); obj->SetPrototypeHClass(thread_, JSTaggedValue::Undefined()); obj->SetNonStaticKeys(thread_, emptyArray, SKIP_BARRIER); obj->SetNonStaticProperties(thread_, emptyArray, SKIP_BARRIER); obj->SetNonStaticElements(thread_, emptyArray, SKIP_BARRIER); obj->SetConstructorHClass(thread_, JSTaggedValue::Undefined()); obj->SetStaticKeys(thread_, emptyArray, SKIP_BARRIER); obj->SetStaticProperties(thread_, emptyArray, SKIP_BARRIER); obj->SetStaticElements(thread_, emptyArray, SKIP_BARRIER); return obj; } // ----------------------------------- new TSType ---------------------------------------- JSHandle ObjectFactory::CreateTSObjLayoutInfo(int propNum, JSTaggedValue initVal) { uint32_t arrayLength = TSObjLayoutInfo::ComputeArrayLength(propNum); JSHandle tsPropInfoHandle = JSHandle::Cast(NewTaggedArray(arrayLength, initVal)); tsPropInfoHandle->SetNumberOfElements(thread_, 0); return tsPropInfoHandle; } JSHandle ObjectFactory::NewTSObjectType(uint32_t numOfKeys) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSObjectTypeClass().GetTaggedObject())); JSHandle objectType(thread_, header); objectType->SetHClass(thread_, JSTaggedValue::Undefined()); objectType->SetObjLayoutInfo(thread_, JSTaggedValue::Undefined()); objectType->SetGTRef(GlobalTSTypeRef::Default()); JSHandle tsPropInfo = CreateTSObjLayoutInfo(numOfKeys); objectType->SetObjLayoutInfo(thread_, tsPropInfo); return objectType; } JSHandle ObjectFactory::NewTSClassType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSClassTypeClass().GetTaggedObject())); JSHandle classType(thread_, header); classType->SetGTRef(GlobalTSTypeRef::Default()); classType->SetInstanceType(thread_, JSTaggedValue::Undefined()); classType->SetConstructorType(thread_, JSTaggedValue::Undefined()); classType->SetPrototypeType(thread_, JSTaggedValue::Undefined()); classType->SetExtensionType(thread_, JSTaggedValue::Undefined()); return classType; } JSHandle ObjectFactory::NewTSInterfaceType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSInterfaceTypeClass().GetTaggedObject())); JSHandle interfaceType(thread_, header); JSHandle extends = EmptyArray(); interfaceType->SetGTRef(GlobalTSTypeRef::Default()); interfaceType->SetExtends(thread_, extends); interfaceType->SetFields(thread_, JSTaggedValue::Undefined()); return interfaceType; } JSHandle ObjectFactory::NewTSUnionType(uint32_t length) { NewObjectHook(); ASSERT(length > 0); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSUnionTypeClass().GetTaggedObject())); JSHandle unionType(thread_, header); unionType->SetGTRef(GlobalTSTypeRef::Default()); unionType->SetComponents(thread_, JSTaggedValue::Undefined()); JSHandle componentTypes = NewTaggedArray(length, JSTaggedValue::Undefined()); unionType->SetComponents(thread_, componentTypes); return unionType; } JSHandle ObjectFactory::NewTSClassInstanceType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSClassInstanceTypeClass().GetTaggedObject())); JSHandle classInstanceType(thread_, header); classInstanceType->SetGTRef(GlobalTSTypeRef::Default()); classInstanceType->SetClassRefGT(GlobalTSTypeRef::Default()); return classInstanceType; } JSHandle ObjectFactory::NewTSImportType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSImportTypeClass().GetTaggedObject())); JSHandle importType(thread_, header); importType->SetGTRef(GlobalTSTypeRef::Default()); importType->SetTargetRefGT(GlobalTSTypeRef::Default()); importType->SetImportPath(thread_, JSTaggedValue::Undefined()); return importType; } JSHandle ObjectFactory::NewTSFunctionType(uint32_t length) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSFunctionTypeClass().GetTaggedObject())); JSHandle functionType(thread_, header); functionType->SetParameterTypes(thread_, JSTaggedValue::Undefined()); JSHandle parameterTypes = NewTaggedArray(length + TSFunctionType::DEFAULT_LENGTH, JSTaggedValue::Undefined()); functionType->SetGTRef(GlobalTSTypeRef::Default()); functionType->SetParameterTypes(thread_, parameterTypes); return functionType; } JSHandle ObjectFactory::NewTSArrayType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSArrayTypeClass().GetTaggedObject())); JSHandle arrayType(thread_, header); arrayType->SetElementTypeRef(0); return arrayType; } JSHandle ObjectFactory::NewTSTypeTable(uint32_t length) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length + TSTypeTable::RESERVE_TABLE_LENGTH); JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); auto header = heap_->AllocateOldOrHugeObject(arrayClass, size); JSHandle table(thread_, header); table->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length + TSTypeTable::RESERVE_TABLE_LENGTH); table->SetNumberOfTypes(thread_, length); return table; } JSHandle ObjectFactory::NewTSModuleTable(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); auto header = heap_->AllocateYoungOrHugeObject(arrayClass, size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); return array; } // ----------------------------------- new string ---------------------------------------- JSHandle ObjectFactory::NewFromASCII(const CString &data) { auto utf8Data = reinterpret_cast(data.c_str()); ASSERT(EcmaString::CanBeCompressed(utf8Data, data.length())); return GetStringFromStringTable(utf8Data, data.length(), true); } JSHandle ObjectFactory::NewFromASCIINonMovable(const CString &data) { auto utf8Data = reinterpret_cast(data.c_str()); ASSERT(EcmaString::CanBeCompressed(utf8Data, data.length())); return GetStringFromStringTableNonMovable(utf8Data, data.length()); } JSHandle ObjectFactory::NewFromUtf8(const CString &data) { auto utf8Data = reinterpret_cast(data.c_str()); bool canBeCompress = EcmaString::CanBeCompressed(utf8Data, data.length()); return GetStringFromStringTable(utf8Data, data.length(), canBeCompress); } JSHandle ObjectFactory::NewFromStdString(const std::string &data) { auto utf8Data = reinterpret_cast(data.c_str()); bool canBeCompress = EcmaString::CanBeCompressed(utf8Data, data.length()); return GetStringFromStringTable(utf8Data, data.size(), canBeCompress); } JSHandle ObjectFactory::NewFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len) { bool canBeCompress = EcmaString::CanBeCompressed(utf8Data, utf8Len); return GetStringFromStringTable(utf8Data, utf8Len, canBeCompress); } JSHandle ObjectFactory::NewFromUtf16(const uint16_t *utf16Data, uint32_t utf16Len) { bool canBeCompress = EcmaString::CanBeCompressed(utf16Data, utf16Len); return GetStringFromStringTable(utf16Data, utf16Len, canBeCompress); } JSHandle ObjectFactory::NewFromUtf16Compress(const uint16_t *utf16Data, uint32_t utf16Len) { ASSERT(EcmaString::CanBeCompressed(utf16Data, utf16Len)); return GetStringFromStringTable(utf16Data, utf16Len, true); } JSHandle ObjectFactory::NewFromUtf16NotCompress(const uint16_t *utf16Data, uint32_t utf16Len) { ASSERT(!EcmaString::CanBeCompressed(utf16Data, utf16Len)); return GetStringFromStringTable(utf16Data, utf16Len, false); } JSHandle ObjectFactory::NewFromUtf8Literal(const uint8_t *utf8Data, uint32_t utf8Len) { NewObjectHook(); bool canBeCompress = EcmaString::CanBeCompressed(utf8Data, utf8Len); return JSHandle(thread_, EcmaString::CreateFromUtf8(utf8Data, utf8Len, vm_, canBeCompress)); } JSHandle ObjectFactory::NewFromUtf8LiteralCompress(const uint8_t *utf8Data, uint32_t utf8Len) { NewObjectHook(); ASSERT(EcmaString::CanBeCompressed(utf8Data, utf8Len)); return JSHandle(thread_, EcmaString::CreateFromUtf8(utf8Data, utf8Len, vm_, true)); } JSHandle ObjectFactory::NewFromUtf16Literal(const uint16_t *utf16Data, uint32_t utf16Len) { NewObjectHook(); bool canBeCompress = EcmaString::CanBeCompressed(utf16Data, utf16Len); return JSHandle(thread_, EcmaString::CreateFromUtf16(utf16Data, utf16Len, vm_, canBeCompress)); } JSHandle ObjectFactory::NewFromUtf16LiteralCompress(const uint16_t *utf16Data, uint32_t utf16Len) { NewObjectHook(); ASSERT(EcmaString::CanBeCompressed(utf16Data, utf16Len)); return JSHandle(thread_, EcmaString::CreateFromUtf16(utf16Data, utf16Len, vm_, true)); } JSHandle ObjectFactory::NewFromUtf16LiteralNotCompress(const uint16_t *utf16Data, uint32_t utf16Len) { NewObjectHook(); ASSERT(!EcmaString::CanBeCompressed(utf16Data, utf16Len)); return JSHandle(thread_, EcmaString::CreateFromUtf16(utf16Data, utf16Len, vm_, false)); } JSHandle ObjectFactory::ConcatFromString(const JSHandle &firstString, const JSHandle &secondString) { if (firstString->GetLength() == 0) { return secondString; } if (secondString->GetLength() == 0) { return firstString; } return GetStringFromStringTable(firstString, secondString); } JSHandle ObjectFactory::GetStringFromStringTable(const JSHandle &firstString, const JSHandle &secondString) { auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(firstString, secondString)); } JSHandle ObjectFactory::NewJSAPIArrayList(uint32_t capacity) { NewObjectHook(); JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetArrayListFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(JSHandle(builtinObj), builtinObj)); ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory(); JSHandle elements = factory->NewTaggedArray(capacity); obj->SetElements(thread_, elements); return obj; } JSHandle ObjectFactory::NewJSAPIArrayListIterator(const JSHandle &arrayList) { NewObjectHook(); JSHandle protoValue(thread_, thread_->GlobalConstants()->GetArrayListIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIArrayListIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedArrayList(thread_, arrayList); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPIPlainArray(array_size_t capacity) { NewObjectHook(); JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetPlainArrayFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(JSHandle(builtinObj), builtinObj)); ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory(); JSHandle keyArray = factory->NewTaggedArray(capacity); JSHandle valueArray = factory->NewTaggedArray(capacity); obj->SetKeys(thread_, keyArray); obj->SetValues(thread_, valueArray); return obj; } JSHandle ObjectFactory::NewJSAPIPlainArrayIterator(const JSHandle &plainarray, IterationKind kind) { NewObjectHook(); JSHandle protoValue(thread_, thread_->GlobalConstants()->GetPlainArrayIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIPlainArrayIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedPlainArray(thread_, plainarray); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPIStackIterator(const JSHandle &stack) { NewObjectHook(); JSHandle protoValue(thread_, thread_->GlobalConstants()->GetStackIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIStackIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedStack(thread_, stack); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::CopyDeque(const JSHandle &old, uint32_t newLength, [[maybe_unused]] uint32_t oldLength, uint32_t first, uint32_t last) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); uint32_t curIndex = first; // newIndex use in new TaggedArray, 0 : New TaggedArray index uint32_t newIndex = 0; uint32_t oldCapacity = old->GetLength(); newArray->SetLength(newLength); while (curIndex != last) { JSTaggedValue value = old->Get(curIndex); newArray->Set(thread_, newIndex, value); ASSERT(oldCapacity != 0); curIndex = (curIndex + 1) % oldCapacity; newIndex = newIndex + 1; } return newArray; } JSHandle ObjectFactory::NewJSAPIDequeIterator(const JSHandle &deque) { NewObjectHook(); JSHandle protoValue(thread_, thread_->GlobalConstants()->GetDequeIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIDequeIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedDeque(thread_, deque); iter->SetNextIndex(deque->GetFirst()); return iter; } JSHandle ObjectFactory::CopyQueue(const JSHandle &old, uint32_t newLength, uint32_t front, uint32_t tail) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); newArray->SetLength(newLength); uint32_t curIndex = front; // newIndex use in new TaggedArray, 0 : New TaggedArray index uint32_t newIndex = 0; uint32_t oldCapacity = old->GetLength(); while (curIndex != tail) { JSTaggedValue value = old->Get(curIndex); newArray->Set(thread_, newIndex, value); ASSERT(oldCapacity != 0); curIndex = (curIndex + 1) % oldCapacity; newIndex = newIndex + 1; } return newArray; } JSHandle ObjectFactory::NewJSAPIQueueIterator(const JSHandle &queue) { NewObjectHook(); JSHandle protoValue(thread_, thread_->GlobalConstants()->GetQueueIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIQueueIteratorClass()); dynHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedQueue(thread_, queue); // IteratedQueue iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPITreeMapIterator(const JSHandle &map, IterationKind kind) { NewObjectHook(); JSHandle proto(thread_, thread_->GlobalConstants()->GetTreeMapIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPITreeMapIteratorClass()); dynHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedMap(thread_, map); iter->SetNextIndex(0); iter->SetEntries(JSTaggedValue::Undefined()); iter->SetIterationKind(kind); JSHandle tmap(thread_, map->GetTreeMap()); JSHandle entries = TaggedTreeMap::GetArrayFromMap(thread_, tmap); iter->SetEntries(thread_, entries); return iter; } JSHandle ObjectFactory::NewJSAPITreeSetIterator(const JSHandle &set, IterationKind kind) { NewObjectHook(); JSHandle proto(thread_, thread_->GlobalConstants()->GetTreeSetIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPITreeSetIteratorClass()); dynHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedSet(thread_, set); iter->SetNextIndex(0); iter->SetEntries(JSTaggedValue::Undefined()); iter->SetIterationKind(kind); JSHandle tset(thread_, set->GetTreeSet()); JSHandle entries = TaggedTreeSet::GetArrayFromSet(thread_, tset); iter->SetEntries(thread_, entries); return iter; } JSHandle ObjectFactory::NewJSAPIVector(uint32_t capacity) { NewObjectHook(); JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetVectorFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(JSHandle(builtinObj), builtinObj)); JSHandle newVector = NewTaggedArray(capacity); obj->SetElements(thread_, newVector); return obj; } JSHandle ObjectFactory::NewJSAPIVectorIterator(const JSHandle &vector) { NewObjectHook(); JSHandle proto(thread_, thread_->GlobalConstants()->GetVectorIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIVectorIteratorClass()); dynHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedVector(thread_, vector); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPILinkedListIterator(const JSHandle &linkedList) { NewObjectHook(); JSHandle proto(thread_, thread_->GlobalConstants()->GetLinkedListIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPILinkedListIteratorClass()); dynHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedLinkedList(thread_, linkedList->GetDoubleList()); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPIListIterator(const JSHandle &List) { NewObjectHook(); JSHandle proto(thread_, thread_->GlobalConstants()->GetListIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle dynHandle(globalConst->GetHandledJSAPIListIteratorClass()); dynHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(dynHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedList(thread_, List->GetSingleList()); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPIList() { NewObjectHook(); JSHandle function(thread_, thread_->GlobalConstants()->GetListFunction()); return JSHandle::Cast(NewJSObjectByConstructor(JSHandle(function), function)); } JSHandle ObjectFactory::NewJSAPILinkedList() { NewObjectHook(); JSHandle function(thread_, thread_->GlobalConstants()->GetLinkedListFunction()); return JSHandle::Cast(NewJSObjectByConstructor(JSHandle(function), function)); } JSHandle ObjectFactory::NewImportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); return NewImportEntry(defautValue, defautValue, defautValue); } JSHandle ObjectFactory::NewImportEntry(const JSHandle &moduleRequest, const JSHandle &importName, const JSHandle &localName) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetImportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModuleRequest(thread_, moduleRequest); obj->SetImportName(thread_, importName); obj->SetLocalName(thread_, localName); return obj; } JSHandle ObjectFactory::NewExportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); return NewExportEntry(defautValue, defautValue, defautValue, defautValue); } JSHandle ObjectFactory::NewExportEntry(const JSHandle &exportName, const JSHandle &moduleRequest, const JSHandle &importName, const JSHandle &localName) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetExportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetExportName(thread_, exportName); obj->SetModuleRequest(thread_, moduleRequest); obj->SetImportName(thread_, importName); obj->SetLocalName(thread_, localName); return obj; } JSHandle ObjectFactory::NewSourceTextModule() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSourceTextModuleClass().GetTaggedObject())); JSHandle obj(thread_, header); JSTaggedValue undefinedValue = thread_->GlobalConstants()->GetUndefined(); obj->SetEnvironment(thread_, undefinedValue); obj->SetNamespace(thread_, undefinedValue); obj->SetEcmaModuleFilename(thread_, undefinedValue); obj->SetRequestedModules(thread_, undefinedValue); obj->SetImportEntries(thread_, undefinedValue); obj->SetLocalExportEntries(thread_, undefinedValue); obj->SetIndirectExportEntries(thread_, undefinedValue); obj->SetStarExportEntries(thread_, undefinedValue); obj->SetNameDictionary(thread_, undefinedValue); obj->SetDFSIndex(SourceTextModule::UNDEFINED_INDEX); obj->SetDFSAncestorIndex(SourceTextModule::UNDEFINED_INDEX); obj->SetEvaluationError(SourceTextModule::UNDEFINED_INDEX); obj->SetStatus(ModuleStatus::UNINSTANTIATED); obj->SetTypes(ModuleTypes::UNKNOWN); return obj; } JSHandle ObjectFactory::NewResolvedBindingRecord() { JSTaggedValue undefinedValue = thread_->GlobalConstants()->GetUndefined(); JSHandle ecmaModule(thread_, undefinedValue); JSHandle bindingName(thread_, undefinedValue); return NewResolvedBindingRecord(ecmaModule, bindingName); } JSHandle ObjectFactory::NewResolvedBindingRecord(const JSHandle &module, const JSHandle &bindingName) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetResolvedBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModule(thread_, module); obj->SetBindingName(thread_, bindingName); return obj; } JSHandle ObjectFactory::NewCellRecord() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCellRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetWeakRefTarget(thread_, JSTaggedValue::Undefined()); obj->SetHeldValue(thread_, JSTaggedValue::Undefined()); return obj; } } // namespace panda::ecmascript