/* * Copyright (c) 2021 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 "js_function.h" #include "ecmascript/base/error_type.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/ecma_runtime_call_info.h" #include "ecmascript/global_env.h" #include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/jspandafile/class_info_extractor.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_proxy.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/object_factory.h" #include "ecmascript/tagged_array.h" namespace panda::ecmascript { void JSFunction::InitializeJSFunction(JSThread *thread, const JSHandle &func, FunctionKind kind, bool strict) { FunctionMode thisMode; if (IsArrowFunction(kind)) { thisMode = FunctionMode::LEXICAL; } else if (strict) { thisMode = FunctionMode::STRICT; } else { thisMode = FunctionMode::GLOBAL; } func->SetProtoOrDynClass(thread, JSTaggedValue::Hole(), SKIP_BARRIER); func->SetHomeObject(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetLexicalEnv(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetModule(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetConstantPool(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetProfileTypeInfo(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetFunctionExtraInfo(thread, JSTaggedValue::Undefined()); func->SetFunctionKind(kind); func->SetStrict(strict); func->SetThisMode(thisMode); func->SetResolved(false); auto globalConst = thread->GlobalConstants(); if (HasPrototype(kind)) { JSHandle accessor = globalConst->GetHandledFunctionPrototypeAccessor(); if (kind == FunctionKind::BASE_CONSTRUCTOR || kind == FunctionKind::GENERATOR_FUNCTION) { func->SetPropertyInlinedProps(thread, PROTOTYPE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); accessor = globalConst->GetHandledFunctionNameAccessor(); func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); } else if (!JSFunction::IsClassConstructor(kind)) { // class ctor do nothing PropertyDescriptor desc(thread, accessor, kind != FunctionKind::BUILTIN_CONSTRUCTOR, false, false); [[maybe_unused]] bool success = JSObject::DefineOwnProperty(thread, JSHandle(func), globalConst->GetHandledPrototypeString(), desc); ASSERT(success); } } else if (HasAccessor(kind)) { JSHandle accessor = globalConst->GetHandledFunctionNameAccessor(); func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); } } JSHandle JSFunction::NewJSFunctionPrototype(JSThread *thread, ObjectFactory *factory, const JSHandle &func) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle objFun = env->GetObjectFunction(); JSHandle funPro = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); func->SetFunctionPrototype(thread, funPro.GetTaggedValue()); // set "constructor" in prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); PropertyDescriptor descriptor(thread, JSHandle::Cast(func), true, false, true); JSObject::DefineOwnProperty(thread, funPro, constructorKey, descriptor); return funPro; } JSHClass *JSFunction::GetOrCreateInitialJSHClass(JSThread *thread, const JSHandle &fun) { JSTaggedValue protoOrDyn(fun->GetProtoOrDynClass()); if (protoOrDyn.IsJSHClass()) { return reinterpret_cast(protoOrDyn.GetTaggedObject()); } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle proto; if (!fun->HasFunctionPrototype()) { proto = JSHandle::Cast(NewJSFunctionPrototype(thread, factory, fun)); } else { proto = JSHandle(thread, fun->GetProtoOrDynClass()); } JSHandle dynclass = factory->NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, proto); fun->SetProtoOrDynClass(thread, dynclass); return *dynclass; } JSTaggedValue JSFunction::PrototypeGetter(JSThread *thread, const JSHandle &self) { JSHandle func = JSHandle::Cast(self); if (!func->HasFunctionPrototype()) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); NewJSFunctionPrototype(thread, factory, func); } return JSFunction::Cast(*self)->GetFunctionPrototype(); } bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle &self, const JSHandle &value, [[maybe_unused]] bool mayThrow) { JSHandle func(self); JSTaggedValue protoOrDyn = func->GetProtoOrDynClass(); if (protoOrDyn.IsJSHClass()) { // need transition JSHandle dynclass(thread, protoOrDyn); JSHandle newDynclass = JSHClass::TransitionProto(thread, dynclass, value); if (value->IsECMAObject()) { JSObject::Cast(value->GetTaggedObject())->GetJSHClass()->SetIsPrototype(true); } func->SetProtoOrDynClass(thread, newDynclass); } else { func->SetFunctionPrototype(thread, value.GetTaggedValue()); } return true; } JSTaggedValue JSFunction::NameGetter(JSThread *thread, const JSHandle &self) { JSMethod *target = JSHandle::Cast(self)->GetCallTarget(); if (target->GetPandaFile() == nullptr) { return JSTaggedValue::Undefined(); } std::string funcName = target->ParseFunctionName(); if (funcName.empty()) { return thread->GlobalConstants()->GetEmptyString(); } if (JSHandle::Cast(self)->GetFunctionKind() == FunctionKind::GETTER_FUNCTION) { funcName.insert(0, "get "); } if (JSHandle::Cast(self)->GetFunctionKind() == FunctionKind::SETTER_FUNCTION) { funcName.insert(0, "set "); } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewFromStdString(funcName).GetTaggedValue(); } bool JSFunction::OrdinaryHasInstance(JSThread *thread, const JSHandle &constructor, const JSHandle &obj) { // 1. If IsCallable(C) is false, return false. if (!constructor->IsCallable()) { return false; } // 2. If C has a [[BoundTargetFunction]] internal slot, then // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot. // b. Return InstanceofOperator(O,BC) (see 12.9.4). if (constructor->IsBoundFunction()) { JSHandle boundFunction(thread, JSBoundFunction::Cast(constructor->GetTaggedObject())); JSTaggedValue boundTarget = boundFunction->GetBoundTarget(); return JSObject::InstanceOf(thread, obj, JSHandle(thread, boundTarget)); } // 3. If Type(O) is not Object, return false if (!obj->IsECMAObject()) { return false; } // 4. Let P be Get(C, "prototype"). const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle constructorPrototype = JSTaggedValue::GetProperty(thread, constructor, globalConst->GetHandledPrototypeString()).GetValue(); // 5. ReturnIfAbrupt(P). // no throw exception, so needn't return RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); // 6. If Type(P) is not Object, throw a TypeError exception. if (!constructorPrototype->IsECMAObject()) { THROW_TYPE_ERROR_AND_RETURN(thread, "HasInstance: is not Object", false); } // 7. Repeat // a.Let O be O.[[GetPrototypeOf]](). // b.ReturnIfAbrupt(O). // c.If O is null, return false. // d.If SameValue(P, O) is true, return true. JSMutableHandle object(thread, obj.GetTaggedValue()); while (!object->IsNull()) { if (JSTaggedValue::SameValue(object, constructorPrototype)) { return true; } object.Update(JSTaggedValue::GetPrototype(thread, object)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); } return false; } bool JSFunction::MakeConstructor(JSThread *thread, const JSHandle &func, const JSHandle &proto, bool writable) { ASSERT_PRINT(proto->IsHeapObject() || proto->IsUndefined(), "proto must be JSObject or Undefined"); ASSERT_PRINT(func->IsConstructor(), "func must be Constructor type"); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle constructorKey = globalConst->GetHandledConstructorString(); ASSERT_PRINT(func->GetProtoOrDynClass().IsHole() && func->IsExtensible(), "function doesn't has proto_type property and is extensible object"); ASSERT_PRINT(JSObject::HasProperty(thread, JSHandle(func), constructorKey), "function must have constructor"); // proto.constructor = func bool status = false; if (proto->IsUndefined()) { // Let prototype be ObjectCreate(%ObjectPrototype%). JSHandle objPrototype = env->GetObjectFunctionPrototype(); PropertyDescriptor constructorDesc(thread, JSHandle::Cast(func), writable, false, true); status = JSTaggedValue::DefinePropertyOrThrow(thread, objPrototype, constructorKey, constructorDesc); } else { PropertyDescriptor constructorDesc(thread, JSHandle::Cast(func), writable, false, true); status = JSTaggedValue::DefinePropertyOrThrow(thread, proto, constructorKey, constructorDesc); } ASSERT_PRINT(status, "DefineProperty construct failed"); // func.prototype = proto // Let status be DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: // prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false}). func->SetFunctionPrototype(thread, proto.GetTaggedValue()); ASSERT_PRINT(status, "DefineProperty proto_type failed"); return status; } JSTaggedValue JSFunction::Call(EcmaRuntimeCallInfo *info) { if (info == nullptr || (info->GetArgsNumber() == INVALID_ARGS_NUMBER)) { return JSTaggedValue::Exception(); } JSThread *thread = info->GetThread(); // 1. ReturnIfAbrupt(F). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle func = info->GetFunction(); // 2. If argumentsList was not passed, let argumentsList be a new empty List. // 3. If IsCallable(F) is false, throw a TypeError exception. if (!func->IsCallable()) { THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception()); } auto *hclass = func->GetTaggedObject()->GetClass(); if (hclass->IsClassConstructor()) { THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call", JSTaggedValue::Exception()); } return EcmaInterpreter::Execute(info); } JSTaggedValue JSFunction::Construct(EcmaRuntimeCallInfo *info) { if (info == nullptr || (info->GetArgsNumber() == INVALID_ARGS_NUMBER)) { return JSTaggedValue::Exception(); } JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); JSMutableHandle target(info->GetNewTarget()); if (target->IsUndefined()) { target.Update(func.GetTaggedValue()); info->SetNewTarget(target.GetTaggedValue()); } if (!(func->IsConstructor() && target->IsConstructor())) { THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception()); } if (func->IsJSFunction()) { return JSFunction::ConstructInternal(info); } else if (func->IsJSProxy()) { return JSProxy::ConstructInternal(info); } else { ASSERT(func->IsBoundFunction()); return JSBoundFunction::ConstructInternal(info); } } JSTaggedValue JSFunction::Invoke(EcmaRuntimeCallInfo *info, const JSHandle &key) { if (info == nullptr || (info->GetArgsNumber() == INVALID_ARGS_NUMBER)) { return JSTaggedValue::Exception(); } ASSERT(JSTaggedValue::IsPropertyKey(key)); JSThread *thread = info->GetThread(); JSHandle thisArg = info->GetThis(); JSHandle func(JSTaggedValue::GetProperty(thread, thisArg, key).GetValue()); info->SetFunction(func.GetTaggedValue()); return JSFunction::Call(info); } // [[Construct]] JSTaggedValue JSFunction::ConstructInternal(EcmaRuntimeCallInfo *info) { if (info == nullptr || (info->GetArgsNumber() == INVALID_ARGS_NUMBER)) { return JSTaggedValue::Exception(); } JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); JSHandle newTarget(info->GetNewTarget()); ASSERT(newTarget->IsECMAObject()); if (!func->IsConstructor()) { THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception()); } JSHandle obj(thread, JSTaggedValue::Undefined()); if (func->IsBase()) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); obj = JSHandle(factory->NewJSObjectByConstructor(func, newTarget)); } info->SetThis(obj.GetTaggedValue()); JSTaggedValue resultValue = EcmaInterpreter::Execute(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 9.3.2 [[Construct]] (argumentsList, newTarget) if (resultValue.IsECMAObject()) { return resultValue; } if (func->IsBase()) { return obj.GetTaggedValue(); } // derived ctor(sub class) return the obj which created by base ctor(parent class) if (func->IsDerivedConstructor()) { return resultValue; } if (!resultValue.IsUndefined()) { THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception()); } return obj.GetTaggedValue(); } JSHandle JSFunctionBase::GetFunctionName(JSThread *thread, const JSHandle &func) { JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); return JSObject::GetProperty(thread, JSHandle(func), nameKey).GetValue(); } bool JSFunctionBase::SetFunctionName(JSThread *thread, const JSHandle &func, const JSHandle &name, const JSHandle &prefix) { ASSERT_PRINT(func->IsExtensible(), "Function must be extensible"); ASSERT_PRINT(name->IsStringOrSymbol(), "name must be string or symbol"); bool needPrefix = false; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); if (!prefix->IsUndefined()) { ASSERT_PRINT(prefix->IsString(), "prefix must be string"); needPrefix = true; } // If Type(name) is Symbol, then // Let description be name’s [[Description]] value. // If description is undefined, let name be the empty String. // Else, let name be the concatenation of "[", description, and "]". JSHandle functionName; if (name->IsSymbol()) { JSTaggedValue description = JSHandle::Cast(name)->GetDescription(); JSHandle descriptionHandle(thread, description); if (description.IsUndefined()) { functionName = factory->GetEmptyString(); } else { JSHandle leftBrackets = JSHandle::Cast(globalConst-> GetHandledLeftSquareBracketString()); JSHandle rightBrackets = JSHandle::Cast(globalConst-> GetHandledRightSquareBracketString()); functionName = factory->ConcatFromString(leftBrackets, descriptionHandle); functionName = factory->ConcatFromString(functionName, rightBrackets); } } else { functionName = JSHandle::Cast(name); } EcmaString *newString; if (needPrefix) { JSHandle handlePrefixString = JSTaggedValue::ToString(thread, prefix); JSHandle spaceString = JSHandle::Cast(globalConst->GetHandledSpaceString()); JSHandle concatString = factory->ConcatFromString(handlePrefixString, spaceString); newString = *factory->ConcatFromString(concatString, functionName); } else { newString = *functionName; } JSHandle nameHandle(thread, newString); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread, nameHandle, false, false, true); JSHandle funcHandle(func); return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, nameKey, nameDesc); } bool JSFunction::SetFunctionLength(JSThread *thread, const JSHandle &func, JSTaggedValue length, bool cfg) { ASSERT_PRINT(func->IsExtensible(), "Function must be extensible"); ASSERT_PRINT(length.IsInteger(), "length must be integer"); JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); ASSERT_PRINT(!JSTaggedValue::Less(thread, JSHandle(thread, length), JSHandle(thread, JSTaggedValue(0))), "length must be non negative integer"); PropertyDescriptor lengthDesc(thread, JSHandle(thread, length), false, false, cfg); JSHandle funcHandle(func); return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, lengthKeyHandle, lengthDesc); } // 9.4.1.2[[Construct]](argumentsList, newTarget) JSTaggedValue JSBoundFunction::ConstructInternal(EcmaRuntimeCallInfo *info) { JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); JSHandle target(thread, func->GetBoundTarget()); ASSERT(target->IsConstructor()); JSHandle newTarget = info->GetNewTarget(); JSMutableHandle newTargetMutable(thread, newTarget.GetTaggedValue()); if (JSTaggedValue::SameValue(func.GetTaggedValue(), newTarget.GetTaggedValue())) { newTargetMutable.Update(target.GetTaggedValue()); } JSHandle boundArgs(thread, func->GetBoundArguments()); const size_t boundLength = boundArgs->GetLength(); const size_t argsLength = info->GetArgsNumber() + boundLength; JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo runtimeInfo = EcmaInterpreter::NewRuntimeCallInfo(thread, target, undefined, newTargetMutable, argsLength); if (boundLength == 0) { runtimeInfo.SetCallArg(argsLength, 0, info, 0); } else { // 0 ~ boundLength is boundArgs; boundLength ~ argsLength is args of EcmaRuntimeCallInfo. runtimeInfo.SetCallArg(boundLength, boundArgs); runtimeInfo.SetCallArg(argsLength, boundLength, info, 0); } return JSFunction::Construct(&runtimeInfo); } void JSProxyRevocFunction::ProxyRevocFunctions(const JSThread *thread, const JSHandle &revoker) { // 1.Let p be the value of F’s [[RevocableProxy]] internal slot. JSTaggedValue proxy = revoker->GetRevocableProxy(); // 2.If p is null, return undefined. if (proxy.IsNull()) { return; } // 3.Set the value of F’s [[RevocableProxy]] internal slot to null. revoker->SetRevocableProxy(thread, JSTaggedValue::Null()); // 4.Assert: p is a Proxy object. ASSERT(proxy.IsJSProxy()); JSHandle proxyHandle(thread, proxy); // 5 ~ 6 Set internal slot of p to null. proxyHandle->SetTarget(thread, JSTaggedValue::Null()); proxyHandle->SetHandler(thread, JSTaggedValue::Null()); } JSTaggedValue JSFunction::AccessCallerArgumentsThrowTypeError([[maybe_unused]] EcmaRuntimeCallInfo *argv) { THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "Under strict mode, 'caller' and 'arguments' properties must not be accessed.", JSTaggedValue::Exception()); } JSTaggedValue JSIntlBoundFunction::IntlNameGetter(JSThread *thread, [[maybe_unused]] const JSHandle &self) { return thread->GlobalConstants()->GetEmptyString(); } void JSFunction::SetFunctionNameNoPrefix(JSThread *thread, JSFunction *func, JSTaggedValue name) { ASSERT_PRINT(func->IsExtensible(), "Function must be extensible"); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle funcHandle(thread, func); { JSMutableHandle nameHandle(thread, JSTaggedValue::Undefined()); if (!name.IsSymbol()) { nameHandle.Update(name); } else { JSHandle nameBegin(thread, name); JSTaggedValue description = JSSymbol::Cast(name.GetTaggedObject())->GetDescription(); if (description.IsUndefined()) { nameHandle.Update(globalConst->GetEmptyString()); } else { JSHandle concatName; JSHandle leftBrackets = JSHandle::Cast(globalConst-> GetHandledLeftSquareBracketString()); JSHandle rightBrackets = JSHandle::Cast(globalConst-> GetHandledRightSquareBracketString()); concatName = factory->ConcatFromString( leftBrackets, JSHandle(thread, JSSymbol::Cast(nameBegin->GetTaggedObject())->GetDescription())); concatName = factory->ConcatFromString(concatName, rightBrackets); nameHandle.Update(concatName.GetTaggedValue()); } } PropertyDescriptor nameDesc(thread, nameHandle, false, false, true); JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, globalConst->GetHandledNameString(), nameDesc); } } JSHandle JSFunction::GetInstanceJSHClass(JSThread *thread, JSHandle constructor, JSHandle newTarget) { JSHandle ctorInitialJSHClass(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor)); // newTarget is construct itself if (newTarget.GetTaggedValue() == constructor.GetTaggedValue()) { return ctorInitialJSHClass; } // newTarget is derived-class of constructor if (newTarget->IsJSFunction()) { JSHandle newTargetFunc = JSHandle::Cast(newTarget); if (newTargetFunc->IsDerivedConstructor()) { JSTaggedValue newTargetProto = JSTaggedValue::GetPrototype(thread, newTarget); if (newTargetProto == constructor.GetTaggedValue()) { return GetOrCreateDerivedJSHClass(thread, newTargetFunc, ctorInitialJSHClass); } } } // ECMA2015 9.1.15 3.Let proto be Get(constructor, "prototype"). JSMutableHandle prototype(thread, JSTaggedValue::Undefined()); if (newTarget->IsJSFunction()) { JSHandle newTargetFunc = JSHandle::Cast(newTarget); FunctionKind kind = newTargetFunc->GetFunctionKind(); if (HasPrototype(kind)) { prototype.Update(PrototypeGetter(thread, JSHandle::Cast(newTargetFunc))); } } else { // Such case: bound function and define a "prototype" property. JSHandle customizePrototype = JSTaggedValue::GetProperty(thread, newTarget, thread->GlobalConstants()->GetHandledPrototypeString()) .GetValue(); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread); prototype.Update(customizePrototype.GetTaggedValue()); // Reload JSHClass of constructor, where the lookup of 'prototype' property may change it. ctorInitialJSHClass = JSHandle(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor)); } if (!prototype->IsECMAObject()) { prototype.Update(constructor->GetFunctionPrototype()); } JSHandle newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass); newJSHClass->SetPrototype(thread, prototype); return newJSHClass; } JSHandle JSFunction::GetOrCreateDerivedJSHClass(JSThread *thread, JSHandle derived, JSHandle ctorInitialJSHClass) { JSTaggedValue protoOrDyn(derived->GetProtoOrDynClass()); // has cached JSHClass, return directly if (protoOrDyn.IsJSHClass()) { return JSHandle(thread, protoOrDyn); } JSHandle newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass); // guarante derived has function prototype JSHandle prototype(thread, derived->GetProtoOrDynClass()); ASSERT(!prototype->IsHole()); newJSHClass->SetPrototype(thread, prototype); derived->SetProtoOrDynClass(thread, newJSHClass); return newJSHClass; } // Those interface below is discarded void JSFunction::InitializeJSFunction(JSThread *thread, [[maybe_unused]] const JSHandle &env, const JSHandle &func, FunctionKind kind, bool strict) { InitializeJSFunction(thread, func, kind, strict); } bool JSFunction::NameSetter(JSThread *thread, const JSHandle &self, const JSHandle &value, [[maybe_unused]] bool mayThrow) { if (self->IsPropertiesDict()) { // replace setter with value JSHandle nameString = thread->GlobalConstants()->GetHandledNameString(); return self->UpdatePropertyInDictionary(thread, nameString.GetTaggedValue(), value.GetTaggedValue()); } self->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, value.GetTaggedValue()); return true; } } // namespace panda::ecmascript