escargot/src/runtime/FunctionObject.h
HyukWoo Park 8fa6031fec Add DerivedObject for sub classes of Object
* check index property set in DerivedObject::defineOwnProperty method only
* index property check is removed for normal Object because PrototypeObject would check it instead

Signed-off-by: HyukWoo Park <hyukwoo.park@samsung.com>
2022-05-11 15:59:43 +09:00

169 lines
5.5 KiB
C++

/*
* Copyright (c) 2016-present Samsung Electronics Co., Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#ifndef __EscargotFunctionObject__
#define __EscargotFunctionObject__
#include "parser/CodeBlock.h"
#include "runtime/Object.h"
#include "runtime/ErrorObject.h"
#include "parser/ScriptParser.h"
namespace Escargot {
class ArrayObject;
class FunctionEnvironmentRecord;
class ScriptFunctionObject;
class ScriptClassConstructorFunctionObject;
class NativeFunctionObject;
class FunctionObjectProcessCallGenerator;
class FunctionObject : public DerivedObject {
friend class Object;
friend class ObjectGetResult;
friend class GlobalObject;
friend class Script;
public:
enum ConstructorKind {
Base,
Derived,
};
// get prototype property of constructible function(not [[prototype]]!!!)
// this property is used for new object construction. see https://www.ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
Value getFunctionPrototype(ExecutionState& state)
{
if (LIKELY(isConstructor() || isGenerator())) {
auto idx = functionPrototypeIndex();
ensureFunctionPrototype(state, idx);
return m_values[idx];
} else {
return Value();
}
}
// set prototype property constructible function(not [[prototype]]!!!)
// this property is used for new object construction. see https://www.ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
bool setFunctionPrototype(ExecutionState& state, const Value& v)
{
if (LIKELY(isConstructor() || isGenerator())) {
m_values[functionPrototypeIndex()] = v;
return true;
} else {
return false;
}
}
virtual bool isGenerator() const
{
return false;
}
virtual bool isFunctionObject() const override
{
return true;
}
virtual bool isCallable() const override
{
return true;
}
CodeBlock* codeBlock() const
{
return m_codeBlock;
}
// https://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects
// internal [[homeObject]] slot
virtual Object* homeObject()
{
return nullptr;
}
virtual Context* getFunctionRealm(ExecutionState& state) override
{
return m_codeBlock->context();
}
struct FunctionSource {
Script* script;
InterpretedCodeBlock* codeBlock;
LexicalEnvironment* outerEnvironment;
};
// create a script for dynamic function
static FunctionSource createDynamicFunctionScript(ExecutionState& state, AtomicString functionName, size_t argCount, Value* argArray, Value bodyString, bool useStrict, bool isGenerator, bool isAsync, bool allowSuperCall, bool isInternalSource = false, String* sourceName = String::emptyString);
// create a general function script which is not a dynamic function
static ScriptParser::InitializeScriptResult createFunctionScript(ExecutionState& state, String* sourceName, AtomicString functionName, size_t argCount, Value* argArray, Value bodyString, bool useStrict);
bool setName(AtomicString name);
protected:
FunctionObject(ExecutionState& state, Object* proto, size_t defaultSpace); // function for derived classes. derived class MUST initlize member variable of FunctionObject.
FunctionObject(ObjectStructure* structure, ObjectPropertyValueVector&& values, Object* proto); // ctor for FunctionTemplate
FunctionObject() // ctor for reading tag
: DerivedObject()
, m_codeBlock(nullptr)
{
}
void initStructureAndValues(ExecutionState& state, bool isConstructor, bool isGenerator);
virtual size_t functionPrototypeIndex()
{
ASSERT(isConstructor() || isGenerator());
return ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER;
}
size_t functionNameIndex()
{
// getting a function name index of ScriptClassConstructorFunctionObject is not supported now
ASSERT(!isScriptClassConstructorFunctionObject());
if (isConstructor() || isGenerator()) {
return ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER + 2;
} else {
return ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER + 1;
}
}
void ensureFunctionPrototype(ExecutionState& state, const size_t& prototypeIndex)
{
if (m_values[prototypeIndex].isEmpty()) {
m_values[prototypeIndex] = createFunctionPrototypeObject(state);
}
}
virtual Object* createFunctionPrototypeObject(ExecutionState& state)
{
return Object::createFunctionPrototypeObject(state, this);
}
static inline void fillGCDescriptor(GC_word* desc)
{
Object::fillGCDescriptor(desc);
GC_set_bit(desc, GC_WORD_OFFSET(FunctionObject, m_codeBlock));
}
CodeBlock* m_codeBlock;
};
} // namespace Escargot
#endif