// -------------------------------------------------------------------------------------------------------------------- HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount) { var functions = from f in (from t in _FunctionsByType.Keys.ToArray() // (need to convert this to an array in case the callbacks modify the dictionary!) select _Engine._GetObjectWeakReference(_FunctionsByType[t])) where f != null && f.Object != null && ((V8Function)f.Object).Callback != null select((V8Function)f.Object).Callback; return(_CallBack(managedObjectID, isConstructCall, _this, args, argCount, functions.ToArray())); }
/// <summary> /// Initializes the handle, linking it permanently with a specified handle proxy. /// </summary> internal Handle _Initialize(HandleProxy *hp) { _UndoPendingDisposal(); _HandleProxy = hp; _ID = -1; _HandleProxy->ManagedHandleID = -1; return(_Reset()); }
bool _V8GarbageCollectionRequestCallback(HandleProxy *persistedObjectHandle) { if (persistedObjectHandle->_ObjectID >= 0) { var weakRef = _GetObjectWeakReference(persistedObjectHandle->_ObjectID); if (weakRef != null) { return(weakRef.Object._OnNativeGCRequested()); // (notify the object that a V8 GC is requested) } } return(true); // (the managed handle doesn't exist, so go ahead and dispose of the native one [the proxy handle]) }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// This is the main entry point from the native side for all calls to functions created from function templates. /// This method exists to give an instance based delegate reference for each function template instance. /// </summary> /// <param name="managedObjectID">The object ID of a managed object for this call.</param> /// <param name="isConstructCall">'true' if this is called because of the 'new' operator in JS.</param> /// <param name="_this">The instance context, if any.</param> /// <param name="args">Any arguments from the JS call.</param> /// <param name="argCount">Number of arguments given in the JS call.</param> /// <returns></returns> HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount) { lock (_FunctionsByType) { // ... get a list of callback functions to execute for this callback ... var functions = from f in (from t in _FunctionsByType.Keys.ToArray() // (need to convert this to an array in case the callbacks modify the dictionary!) select _Engine._GetExistingObject(_FunctionsByType[t])) where f != null && ((V8Function)f.Object).Callback != null select((V8Function)f.Object).Callback; return(_CallBack(managedObjectID, isConstructCall, _this, args, argCount, functions.ToArray())); } }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Returns an existing or new handle to wrap the proxy reference. /// </summary> internal Handle _GetHandle(HandleProxy *hp) { _DoWorkStep(); // (attempt to dispose of at least one handle on each call to attempt to keep reusing handles whenever possible) if (hp == null) { return(null); } if (hp->ManagedHandleID >= 0) { return(_Handles[hp->ManagedHandleID].Object._Reset()); } Handle handle; switch (hp->ValueType) { case JSValueType.Bool: handle = new Handle <bool>(this); break; case JSValueType.Date: handle = new Handle <DateTime>(this); break; case JSValueType.Int32: handle = new Handle <Int32>(this); break; case JSValueType.Number: handle = new Handle <double>(this); break; case JSValueType.String: handle = new Handle <string>(this); break; case JSValueType.CompilerError: handle = new Handle <string>(this); break; case JSValueType.ExecutionError: handle = new Handle <string>(this); break; case JSValueType.InternalError: handle = new Handle <string>(this); break; default: handle = new Handle <object>(this); break; } handle._Initialize(hp); lock (_Handles) // (whole list may be affected internally, so this needs to be thread protected) { hp->ManagedHandleID = handle._ID = _Handles.Add(new ObservableWeakReference <Handle>(handle)); } return(handle); }
protected HandleProxy *_IndexedPropertySetter(Int32 index, HandleProxy *value, ref ManagedAccessorInfo info) { try { using (InternalHandle hValue = new InternalHandle(value, false)) { var obj = _Engine._GetObjectWeakReference(info.ManagedObjectID); if (obj == null) { return(null); } var mo = obj.Reset() as IV8ManagedObject; return(mo != null?mo.IndexedPropertySetter(index, hValue) : null); } } catch (Exception ex) { return(_Engine.CreateError(Exceptions.GetFullErrorMessage(ex), JSValueType.ExecutionError)); } }
protected HandleProxy *_IndexedPropertySetter(Int32 index, HandleProxy *value, ref ManagedAccessorInfo info) { try { InternalHandle hValue = value; var obj = _Engine._GetExistingObject(info.ManagedObjectID); if (obj == null) { return(null); } var mo = obj as IV8ManagedObject; var result = mo != null?mo.IndexedPropertySetter(index, hValue) : null; return(result); } catch (Exception ex) { return(_Engine.CreateError(Exceptions.GetFullErrorMessage(ex), JSValueType.ExecutionError)); } }
public static extern void UpdateHandleValue(HandleProxy *handle);
public static extern void MakeStrongHandle(HandleProxy *handleProxy);
public static unsafe extern void SetFunctionTemplateProperty(NativeFunctionTemplateProxy *proxy, string name, HandleProxy *value, V8PropertyAttributes attributes = V8PropertyAttributes.None);
public static unsafe extern V8PropertyAttributes GetPropertyAttributes(HandleProxy *proxy, string name);
public static unsafe extern void SetObjectAccessor(HandleProxy *proxy, Int32 managedObjectID, string name, ManagedAccessorGetter getter, ManagedAccessorSetter setter, V8AccessControl access, V8PropertyAttributes attributes);
public static unsafe extern bool DeleteObjectPropertyByName(HandleProxy *proxy, string name);
/// <summary> /// If there's any marshalling incompatibility, this will throw an exception. /// </summary> public void RunMarshallingTests() { HandleProxy * hp = V8NetProxy.CreateHandleProxyTest(); NativeV8EngineProxy * nv8ep = V8NetProxy.CreateV8EngineProxyTest(); NativeObjectTemplateProxy * notp = V8NetProxy.CreateObjectTemplateProxyTest(); NativeFunctionTemplateProxy *nftp = V8NetProxy.CreateFunctionTemplateProxyTest(); byte[] data; byte ofs = 0; // (skip type) try { ofs = (byte)((int)&hp->NativeClassType - (int)hp); if (hp->NativeClassType != ProxyObjectType.HandleProxyClass) { _ThrowMarshalTestError("HandleProxy", "NativeClassType", ofs, null, (byte *)&hp->NativeClassType, 4); } ofs = (byte)((int)&hp->ID - (int)hp); if ((Int32)hp->ID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "ID", ofs, data, (byte *)&hp->ID); } ofs = (byte)((int)&hp->_ObjectID - (int)hp); if ((Int32)hp->_ObjectID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "_ObjectID", ofs, data, (byte *)&hp->_ObjectID); } ofs = (byte)((int)&hp->_CLRTypeID - (int)hp); if ((Int32)hp->_CLRTypeID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "_CLRTypeID", ofs, data, (byte *)&hp->_CLRTypeID); } ofs = (byte)((int)&hp->_Type - (int)hp); if ((Int32)hp->_Type != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "_ValueType", ofs, data, (byte *)&hp->_Type); } // region ### HANDLE VALUE ### - Note: This is only valid upon calling 'UpdateValue()'. ofs = (byte)((int)&hp->V8Boolean - (int)hp); if ((byte)hp->V8Boolean != _GetMarshalTestByteValue(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "V8Boolean", ofs, data, (byte *)&hp->V8Boolean); } if ((Int64)hp->V8Integer != _GetMarshalTestInt64Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "V8Integer", ofs, data, (byte *)&hp->V8Integer); } if ((double)hp->V8Number != _GetMarshalTestDoubleValue(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "V8Number", ofs, data, (byte *)&hp->V8Number); } ofs = (byte)((int)&hp->V8String - (int)hp); if ((Int64)hp->V8String != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "V8String", ofs, data, (byte *)&hp->V8String); } // endregion ofs = (byte)((int)&hp->ManagedReference - (int)hp); if ((Int64)hp->ManagedReference != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "ManagedReference", ofs, data, (byte *)&hp->ManagedReference); // The number of references on the managed side. } ofs = (byte)((int)&hp->Disposed - (int)hp); if ((Int32)hp->Disposed != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "Disposed", ofs, data, (byte *)&hp->Disposed); // (0 = in use, 1 = managed side ready to dispose, 2 = object is weak (if applicable), 3 = disposed/cached) } ofs = (byte)((int)&hp->EngineID - (int)hp); if ((Int32)hp->EngineID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "EngineID", ofs, data, (byte *)&hp->EngineID); } ofs = (byte)((int)&hp->NativeEngineProxy - (int)hp); if ((Int64)hp->NativeEngineProxy != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "NativeEngineProxy", ofs, data, (byte *)&hp->NativeEngineProxy); // Pointer to the native V8 engine proxy object associated with this proxy handle instance (used native side to free the handle upon destruction). } ofs = (byte)((int)&hp->NativeV8Handle - (int)hp); if ((Int64)hp->NativeV8Handle != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("HandleProxy", "NativeV8Handle", ofs, data, (byte *)&hp->NativeV8Handle); // The native V8 persistent object handle (not used on the managed side). } ofs = (byte)((int)&nv8ep->NativeClassType - (int)nv8ep); if (nv8ep->NativeClassType != ProxyObjectType.V8EngineProxyClass) { _ThrowMarshalTestError("NativeV8EngineProxy", "NativeClassType", ofs, null, (byte *)&nv8ep->NativeClassType, 4); } ofs = (byte)((int)&nv8ep->ID - (int)nv8ep); if ((Int32)nv8ep->ID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("NativeV8EngineProxy", "ID", ofs, data, (byte *)&nv8ep->ID); } ofs += (byte)data.Length; ofs = (byte)((int)¬p->NativeClassType - (int)notp); if (notp->NativeClassType != ProxyObjectType.ObjectTemplateProxyClass) { _ThrowMarshalTestError("NativeObjectTemplateProxy", "NativeClassType", ofs, null, (byte *)¬p->NativeClassType, 4); } ofs = (byte)((int)¬p->NativeEngineProxy - (int)notp); if ((Int64)notp->NativeEngineProxy != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("NativeObjectTemplateProxy", "NativeEngineProxy", ofs, data, (byte *)¬p->NativeEngineProxy); } ofs = (byte)((int)¬p->EngineID - (int)notp); if ((Int32)notp->EngineID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("NativeObjectTemplateProxy", "EngineID", ofs, data, (byte *)¬p->EngineID); } ofs = (byte)((int)¬p->ObjectID - (int)notp); if ((Int32)notp->ObjectID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("NativeObjectTemplateProxy", "ObjectID", ofs, data, (byte *)¬p->ObjectID); } ofs = (byte)((int)¬p->NativeObjectTemplate - (int)notp); if ((Int64)notp->NativeObjectTemplate != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("NativeObjectTemplateProxy", "NativeObjectTemplate", ofs, data, (byte *)¬p->NativeObjectTemplate); } ofs = (byte)((int)&nftp->NativeClassType - (int)nftp); if (nftp->NativeClassType != ProxyObjectType.FunctionTemplateProxyClass) { _ThrowMarshalTestError("NativeFunctionTemplateProxy", "NativeClassType", ofs, null, (byte *)&nftp->NativeClassType, 4); } ofs = (byte)((int)&nftp->NativeEngineProxy - (int)nftp); if ((Int64)nftp->NativeEngineProxy != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("NativeFunctionTemplateProxy", "NativeEngineProxy", ofs, data, (byte *)&nftp->NativeEngineProxy); } ofs = (byte)((int)&nftp->EngineID - (int)nftp); if ((Int32)nftp->EngineID != _GetMarshalTestInt32Value(ofs, out data)) { _ThrowMarshalTestError("NativeFunctionTemplateProxy", "EngineID", ofs, data, (byte *)&nftp->EngineID); } ofs = (byte)((int)&nftp->NativeFucntionTemplate - (int)nftp); if ((Int64)nftp->NativeFucntionTemplate != _GetMarshalTestPTRValue(ofs, out data)) { _ThrowMarshalTestError("NativeFunctionTemplateProxy", "NativeFucntionTemplate", ofs, data, (byte *)&nftp->NativeFucntionTemplate); } } finally { V8NetProxy.DeleteTestData(hp); V8NetProxy.DeleteTestData(nv8ep); V8NetProxy.DeleteTestData(notp); V8NetProxy.DeleteTestData(nftp); } }
public static unsafe extern void SetObjectTemplateProperty32(NativeObjectTemplateProxy *proxy, string name, HandleProxy *value, V8PropertyAttributes attributes = V8PropertyAttributes.None);
public static unsafe extern HandleProxy *GetObjectPropertyByName(HandleProxy *proxy, string name);
public static unsafe extern HandleProxy *GetObjectPropertyByIndex(HandleProxy *proxy, Int32 index);
// TODO: This is shared in both templates - consider putting elsewhere. internal static HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount, params JSFunction[] functions) { // ... get a handle to the native "this" object ... InternalHandle hThis = _this; V8Engine engine = hThis.Engine; // ... wrap the arguments ... InternalHandle[] _args = new InternalHandle[argCount]; int i; for (i = 0; i < argCount; i++) { _args[i] = args[i]; // (since these will be disposed immediately after, the "first" flag is not required [this also prevents it from getting passed on]) } // (note: the underlying native handles for '_this' and any arguments will be disposed automatically upon return, unless the user calls 'KeepAlive()' on them) InternalHandle result = null; // ... call all function types (multiple custom derived function types are allowed, but only one of each type) ... foreach (var callback in functions) { result = callback(engine, isConstructCall, hThis, _args); if (!result.IsEmpty) { break; } } var obj = result.Object; // ... make sure the user is not returning a 'V8ManagedObject' instance associated with the new object (the property interceptors will never work) ... if (isConstructCall && obj != null && obj is V8ManagedObject && obj.InternalHandle == hThis) { throw new InvalidOperationException("You've attempted to return the type '" + obj.GetType().Name + "' which is of type V8ManagedObject in a construction call (using 'new' in JavaScript) to wrap the new native object given to the constructor. The native V8 engine" + " only supports interceptor hooks for objects generated from ObjectTemplate instances. You will need to first derive/implement from V8NativeObject/IV8NativeObject" + " for your custom object(s), or rewrite your object to use V8NativeObject directly instead and use the 'SetAccessor()' handle method."); } return(result); }
public static unsafe extern bool DeleteObjectPropertyByIndex(HandleProxy *proxy, Int32 index);
public static extern HandleProxy *V8ExecuteCompiledScript(NativeV8EngineProxy *engine, HandleProxy *script);
public static unsafe extern HandleProxy *GetOwnPropertyNames(HandleProxy *proxy);
public static unsafe extern void ConnectObject(HandleProxy *handleProxy, Int32 objID, void *templateProxy = null);
public static unsafe extern Int32 GetArrayLength(HandleProxy *proxy);
public static unsafe extern HandleProxy *GetObjectPrototype(HandleProxy *handleProxy);
public static extern void MakeWeakHandle(HandleProxy *handleProxy);
/// <summary> /// Calls a property with a given name on a specified object as a function and returns the result. /// If the function name is null, then the subject is assumed to be a function object. /// </summary> public static unsafe extern HandleProxy *Call(HandleProxy *subject, string functionName, HandleProxy *_this, Int32 argCount, HandleProxy **args);
public static extern void DisposeHandleProxy(HandleProxy *handle);
public static unsafe extern bool SetObjectPropertyByName(HandleProxy *proxy, string name, HandleProxy *value, V8PropertyAttributes attributes = V8PropertyAttributes.None);
public static extern int GetHandleManagedObjectID(HandleProxy *handle);
public static unsafe extern bool SetObjectPropertyByIndex(HandleProxy *proxy, Int32 index, HandleProxy *value);