blob: d4f95c9859921a4da12c0b4fb0a2668f2c23a1ca [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
// Implements JavascriptProxy.
//----------------------------------------------------------------------------
#pragma once
namespace Js
{
// Host should keep the same object in cross-site scenario.
class JavascriptProxy : public DynamicObject
{
friend class JavascriptOperators;
protected:
DEFINE_VTABLE_CTOR(JavascriptProxy, DynamicObject);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptProxy);
private:
Field(RecyclableObject*) handler;
Field(RecyclableObject*) target;
void RevokeObject();
public:
static const uint32 MAX_STACK_CALL_ARGUMENT_COUNT = 20;
class EntryInfo
{
public:
static FunctionInfo NewInstance;
static FunctionInfo Revocable;
static FunctionInfo Revoke;
};
typedef enum SetPropertyTrapKind {
SetItemOnTaggedNumberKind,
SetPropertyOnTaggedNumberKind,
SetPropertyKind,
SetItemKind,
SetPropertyWPCacheKind,
} SetPropertyTrapKind;
enum KeysTrapKind {
GetOwnPropertyNamesKind,
GetOwnPropertySymbolKind,
KeysKind
};
enum IntegrityLevel {
IntegrityLevel_sealed,
IntegrityLevel_frozen
};
JavascriptProxy(DynamicType * type);
JavascriptProxy(DynamicType * type, ScriptContext * scriptContext, RecyclableObject* target, RecyclableObject* handler);
static BOOL Is(Var obj);
static JavascriptProxy* FromVar(Var obj) { Assert(Is(obj)); return static_cast<JavascriptProxy*>(obj); }
#ifndef IsJsDiag
RecyclableObject* GetTarget();
RecyclableObject* GetHandler();
#else
RecyclableObject* GetTarget() { return target; }
RecyclableObject* GetHandler() { return handler; }
#endif
static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryRevocable(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryRevoke(RecyclableObject* function, CallInfo callInfo, ...);
static Var FunctionCallTrap(RecyclableObject* function, CallInfo callInfo, ...);
static JavascriptProxy* Create(ScriptContext* scriptContext, Arguments args);
static BOOL GetOwnPropertyDescriptor(RecyclableObject* obj, PropertyId propertyId, ScriptContext* scriptContext, PropertyDescriptor* propertyDescriptor);
static BOOL DefineOwnPropertyDescriptor(RecyclableObject* obj, PropertyId propId, const PropertyDescriptor& descriptor, bool throwOnError, ScriptContext* scriptContext);
static DWORD GetOffsetOfTarget() { return offsetof(JavascriptProxy, target); }
virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId) override;
virtual BOOL HasOwnProperty(PropertyId propertyId) override;
virtual BOOL HasOwnPropertyNoHostObject(PropertyId propertyId) override;
virtual BOOL HasOwnPropertyCheckNoRedecl(PropertyId propertyId) override;
virtual BOOL UseDynamicObjectForNoHostObjectAccess() override;
virtual DescriptorFlags GetSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual BOOL GetInternalProperty(Var instance, PropertyId internalPropertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual BOOL GetAccessors(PropertyId propertyId, Var* getter, Var* setter, ScriptContext * requestContext) override;
virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
virtual BOOL SetInternalProperty(PropertyId internalPropertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
virtual BOOL InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags = PropertyOperation_None, PropertyValueInfo* info = NULL) override;
virtual BOOL EnsureProperty(PropertyId propertyId) override;
virtual BOOL EnsureNoRedeclProperty(PropertyId propertyId) override;
virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;
virtual BOOL InitPropertyScoped(PropertyId propertyId, Var value) override;
virtual BOOL InitFuncScoped(PropertyId propertyId, Var value) override;
virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags) override;
virtual BOOL DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags) override;
virtual BOOL IsFixedProperty(PropertyId propertyId) override;
virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
virtual BOOL HasOwnItem(uint32 index) override;
virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override;
virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, ForInCache * forInCache = nullptr) override;
virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None) override;
virtual BOOL Equals(__in Var other, __out BOOL* value, ScriptContext* requestContext) override;
virtual BOOL StrictEquals(__in Var other, __out BOOL* value, ScriptContext* requestContext) override;
virtual BOOL IsWritable(PropertyId propertyId) override;
virtual BOOL IsConfigurable(PropertyId propertyId) override;
virtual BOOL IsEnumerable(PropertyId propertyId) override;
virtual BOOL IsExtensible() override;
virtual BOOL PreventExtensions() override;
virtual void ThrowIfCannotDefineProperty(PropertyId propId, const PropertyDescriptor& descriptor) { }
virtual void ThrowIfCannotGetOwnPropertyDescriptor(PropertyId propId) {};
virtual BOOL GetDefaultPropertyDescriptor(PropertyDescriptor& descriptor) override;
virtual BOOL Seal() override;
virtual BOOL Freeze() override;
virtual BOOL IsSealed() override;
virtual BOOL IsFrozen() override;
virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;
virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;
virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;
virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) override;
virtual BOOL GetSpecialPropertyName(uint32 index, JavascriptString ** propertyName, ScriptContext * requestContext) { return false; }
virtual uint GetSpecialPropertyCount() const { return 0; }
virtual PropertyId const * GetSpecialPropertyIds() const { return nullptr; }
virtual BOOL HasInstance(Var instance, ScriptContext* scriptContext, IsInstInlineCache* inlineCache = NULL) override;
// This is used for external object only; should not be called for proxy
virtual RecyclableObject* GetConfigurablePrototype(ScriptContext * requestContext) override;
virtual RecyclableObject* GetPrototypeSpecial() override;
// for external object. don't need it here.
virtual Js::JavascriptString* GetClassName(ScriptContext * requestContext) override;
#if DBG
virtual bool CanStorePropertyValueDirectly(PropertyId propertyId, bool allowLetConst) { Assert(false); return false; };
#endif
virtual void RemoveFromPrototype(ScriptContext * requestContext) override;
virtual void AddToPrototype(ScriptContext * requestContext) override;
virtual void SetPrototype(RecyclableObject* newPrototype) override;
BOOL SetPrototypeTrap(RecyclableObject* newPrototype, bool showThrow);
Var ToString(Js::ScriptContext* scriptContext);
// proxy does not support IDispatch stuff.
virtual Var GetNamespaceParent(Js::Var aChild) { AssertMsg(false, "Shouldn't call this implementation."); return nullptr; }
virtual HRESULT QueryObjectInterface(REFIID riid, void **ppvObj) { AssertMsg(false, "Shouldn't call this implementation."); return E_NOTIMPL; }
virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
virtual RecyclableObject* ToObject(ScriptContext * requestContext) override;
virtual Var GetTypeOfString(ScriptContext* requestContext) override;
BOOL SetPropertyTrap(Var receiver, SetPropertyTrapKind setPropertyTrapKind, PropertyId propertyId, Var newValue, ScriptContext* requestContext, BOOL skipPrototypeCheck = FALSE);
BOOL SetPropertyTrap(Var receiver, SetPropertyTrapKind setPropertyTrapKind, Js::JavascriptString * propertyString, Var newValue, ScriptContext* requestContext);
void PropertyIdFromInt(uint32 index, PropertyRecord const** propertyRecord);
JavascriptArray* PropertyKeysTrap(KeysTrapKind keysTrapKind, ScriptContext* requestContext);
template <class Fn>
void GetOwnPropertyKeysHelper(ScriptContext* scriptContext, RecyclableObject* trapResultArray, uint32 len, JavascriptArray* trapResult,
JsUtil::BaseDictionary<Js::PropertyId, bool, ArenaAllocator>& targetToTrapResultMap, Fn fn)
{
Var element;
const PropertyRecord* propertyRecord;
uint32 trapResultIndex = 0;
PropertyId propertyId;
for (uint32 i = 0; i < len; i++)
{
if (!JavascriptOperators::GetItem(trapResultArray, i, &element, scriptContext))
continue;
if (!(JavascriptString::Is(element) || JavascriptSymbol::Is(element)))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_InconsistentTrapResult, _u("ownKeys"));
}
JavascriptConversion::ToPropertyKey(element, scriptContext, &propertyRecord);
propertyId = propertyRecord->GetPropertyId();
if (!targetToTrapResultMap.ContainsKey(propertyId))
{
if (propertyId != Constants::NoProperty)
{
targetToTrapResultMap.Add(propertyId, true);
}
if (fn(propertyRecord))
{
trapResult->DirectSetItemAt(trapResultIndex++, element);
}
}
}
}
Var ConstructorTrap(Arguments args, ScriptContext* scriptContext, const Js::AuxArray<uint32> *spreadIndices);
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
static PropertyId EnsureHandlerPropertyId(ScriptContext* scriptContext);
static RecyclableObject* AutoProxyWrapper(Var obj);
#endif
private:
JavascriptFunction* GetMethodHelper(PropertyId methodId, ScriptContext* requestContext);
Var GetValueFromDescriptor(Var instance, PropertyDescriptor propertyDescriptor, ScriptContext* requestContext);
static Var GetName(ScriptContext* requestContext, PropertyId propertyId);
static BOOL TestIntegrityLevel(IntegrityLevel integrityLevel, RecyclableObject* obj, ScriptContext* scriptContext);
static BOOL SetIntegrityLevel(IntegrityLevel integrityLevel, RecyclableObject* obj, ScriptContext* scriptContext);
template <class Fn, class GetPropertyIdFunc>
BOOL HasPropertyTrap(Fn fn, GetPropertyIdFunc getPropertyId);
template <class Fn, class GetPropertyIdFunc>
BOOL GetPropertyTrap(Var instance, PropertyDescriptor* propertyDescriptor, Fn fn, GetPropertyIdFunc getPropertyId, ScriptContext* requestContext);
template <class Fn, class GetPropertyIdFunc>
BOOL GetPropertyDescriptorTrap(Var originalInstance, Fn fn, GetPropertyIdFunc getPropertyId, PropertyDescriptor* resultDescriptor, ScriptContext* requestContext);
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
}