#include "config.h"
#include "ReflectObject.h"
#include "BuiltinNames.h"
#include "JSCInlines.h"
#include "JSGlobalObjectFunctions.h"
#include "JSPropertyNameIterator.h"
#include "Lookup.h"
#include "ObjectConstructor.h"
namespace JSC {
static EncodedJSValue JSC_HOST_CALL reflectObjectConstruct(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectDefineProperty(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectEnumerate(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectGet(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectGetOwnPropertyDescriptor(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectGetPrototypeOf(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectIsExtensible(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectOwnKeys(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectPreventExtensions(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectSet(ExecState*);
static EncodedJSValue JSC_HOST_CALL reflectObjectSetPrototypeOf(ExecState*);
}
#include "ReflectObject.lut.h"
namespace JSC {
STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ReflectObject);
const ClassInfo ReflectObject::s_info = { "Object", &Base::s_info, &reflectObjectTable, CREATE_METHOD_TABLE(ReflectObject) };
ReflectObject::ReflectObject(VM& vm, Structure* structure)
: JSNonFinalObject(vm, structure)
{
}
void ReflectObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().ownKeysPrivateName(), reflectObjectOwnKeys, DontEnum | DontDelete | ReadOnly, 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getOwnPropertyDescriptorPrivateName(), reflectObjectGetOwnPropertyDescriptor, DontEnum | DontDelete | ReadOnly, 2);
}
EncodedJSValue JSC_HOST_CALL reflectObjectConstruct(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.construct requires the first argument be a constructor")));
ConstructData constructData;
ConstructType constructType;
if (!target.isConstructor(constructType, constructData))
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.construct requires the first argument be a constructor")));
JSValue newTarget = target;
if (exec->argumentCount() >= 3) {
newTarget = exec->argument(2);
if (!newTarget.isConstructor())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.construct requires the third argument be a constructor if present")));
}
MarkedArgumentBuffer arguments;
JSObject* argumentsObject = jsDynamicCast<JSObject*>(exec->argument(1));
if (!argumentsObject)
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.construct requires the second argument be an object")));
createListFromArrayLike(exec, argumentsObject, RuntimeTypeMaskAllTypes, ASCIILiteral("This error must not be raised"), [&] (JSValue value, RuntimeType) -> bool {
arguments.append(value);
return false;
});
RETURN_IF_EXCEPTION(scope, encodedJSValue());
scope.release();
return JSValue::encode(construct(exec, target, constructType, constructData, arguments, newTarget));
}
EncodedJSValue JSC_HOST_CALL reflectObjectDefineProperty(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.defineProperty requires the first argument be an object")));
auto propertyName = exec->argument(1).toPropertyKey(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
PropertyDescriptor descriptor;
bool success = toPropertyDescriptor(exec, exec->argument(2), descriptor);
ASSERT(!scope.exception() == success);
if (UNLIKELY(!success))
return encodedJSValue();
ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
ASSERT(!scope.exception());
bool shouldThrow = false;
JSObject* targetObject = asObject(target);
scope.release();
return JSValue::encode(jsBoolean(targetObject->methodTable(vm)->defineOwnProperty(targetObject, exec, propertyName, descriptor, shouldThrow)));
}
EncodedJSValue JSC_HOST_CALL reflectObjectEnumerate(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.enumerate requires the first argument be an object")));
scope.release();
return JSValue::encode(JSPropertyNameIterator::create(exec, exec->lexicalGlobalObject()->propertyNameIteratorStructure(), asObject(target)));
}
EncodedJSValue JSC_HOST_CALL reflectObjectGet(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.get requires the first argument be an object")));
const Identifier propertyName = exec->argument(1).toPropertyKey(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
JSValue receiver = target;
if (exec->argumentCount() >= 3)
receiver = exec->argument(2);
PropertySlot slot(receiver, PropertySlot::InternalMethodType::Get);
scope.release();
return JSValue::encode(target.get(exec, propertyName, slot));
}
EncodedJSValue JSC_HOST_CALL reflectObjectGetOwnPropertyDescriptor(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.getOwnPropertyDescriptor requires the first argument be an object")));
auto key = exec->argument(1).toPropertyKey(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
scope.release();
return JSValue::encode(objectConstructorGetOwnPropertyDescriptor(exec, asObject(target), key));
}
EncodedJSValue JSC_HOST_CALL reflectObjectGetPrototypeOf(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.getPrototypeOf requires the first argument be an object")));
scope.release();
return JSValue::encode(asObject(target)->getPrototype(vm, exec));
}
EncodedJSValue JSC_HOST_CALL reflectObjectIsExtensible(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.isExtensible requires the first argument be an object")));
bool isExtensible = asObject(target)->isExtensible(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
return JSValue::encode(jsBoolean(isExtensible));
}
EncodedJSValue JSC_HOST_CALL reflectObjectOwnKeys(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.ownKeys requires the first argument be an object")));
scope.release();
return JSValue::encode(ownPropertyKeys(exec, jsCast<JSObject*>(target), PropertyNameMode::StringsAndSymbols, DontEnumPropertiesMode::Include));
}
EncodedJSValue JSC_HOST_CALL reflectObjectPreventExtensions(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.preventExtensions requires the first argument be an object")));
JSObject* object = asObject(target);
bool result = object->methodTable(vm)->preventExtensions(object, exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
return JSValue::encode(jsBoolean(result));
}
EncodedJSValue JSC_HOST_CALL reflectObjectSet(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.set requires the first argument be an object")));
JSObject* targetObject = asObject(target);
auto propertyName = exec->argument(1).toPropertyKey(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
JSValue receiver = target;
if (exec->argumentCount() >= 4)
receiver = exec->argument(3);
bool shouldThrowIfCantSet = false;
PutPropertySlot slot(receiver, shouldThrowIfCantSet);
scope.release();
return JSValue::encode(jsBoolean(targetObject->methodTable(vm)->put(targetObject, exec, propertyName, exec->argument(2), slot)));
}
EncodedJSValue JSC_HOST_CALL reflectObjectSetPrototypeOf(ExecState* exec)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.setPrototypeOf requires the first argument be an object")));
JSValue proto = exec->argument(1);
if (!proto.isObject() && !proto.isNull())
return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.setPrototypeOf requires the second argument be either an object or null")));
JSObject* object = asObject(target);
bool shouldThrowIfCantSet = false;
bool didSetPrototype = object->setPrototype(vm, exec, proto, shouldThrowIfCantSet);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
return JSValue::encode(jsBoolean(didSetPrototype));
}
}