// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Calls the V8 'SetAccessor()' function on the underlying native object to create a property that is controlled by /// "getter" and "setter" callbacks. /// <para>WARNING: If you try to set managed accessors on a native-ONLY object (as in, this handle does not yet have a /// managed-side object associated with it) then /// <see cref="V8Engine.CreateObject(InternalHandle, bool)"/> will be called to create a wrapper object so the /// accessor delegates will not get garbage collected, causing errors. You can optionally take control of this yourself /// and call one of the 'CreateObject()' methods on <see cref="V8Engine"/>.</para> /// </summary> /// <param name="name"> The property name. </param> /// <param name="getter"> /// The property getter delegate that returns a value when the property is accessed within JavaScript. /// </param> /// <param name="setter"> /// The property setter delegate that sets AND returns a value when the property is accessed within JavaScript. /// </param> /// <param name="attributes"> (Optional) The attributes to assign to the property. </param> /// <param name="access"> (Optional) The access security on the property. </param> /// <seealso cref="M:V8.Net.IV8Object.SetAccessor(string,GetterAccessor,SetterAccessor,V8PropertyAttributes,V8AccessControl)"/> public virtual void SetAccessor(string name, GetterAccessor getter, SetterAccessor setter, V8PropertyAttributes attributes = V8PropertyAttributes.None, V8AccessControl access = V8AccessControl.Default) { attributes = _CreateAccessorProxies(Engine, name, getter, setter, attributes, access, ref _Getter, ref _Setter); Getter = getter; Setter = setter; V8NetProxy.SetObjectAccessor(this, ID, name, _Getter, _Setter, access, attributes); }
/// <summary> /// Calls the V8 'SetAccessor()' function on the underlying native 'v8::ObjectTenplate' instance to create a property that is controlled by "getter" and "setter" callbacks. /// <para>Note: This is template related, which means all objects created from this template will be affected by these special properties.</para> /// </summary> public void SetAccessor(string name, GetterAccessor getter, SetterAccessor setter, V8PropertyAttributes attributes = V8PropertyAttributes.None, V8AccessControl access = V8AccessControl.Default) { attributes = V8NativeObject._CreateAccessorProxies(Engine, name, getter, setter, attributes, access, ref _Getter, ref _Setter); Getter = getter; Setter = setter; V8NetProxy.SetObjectTemplateAccessor(_NativeObjectTemplateProxy, -1, name, _Getter, _Setter, access, attributes); }
static internal V8PropertyAttributes _CreateAccessorProxies(V8Engine engine, string name, GetterAccessor getter, SetterAccessor setter, V8PropertyAttributes attributes, V8AccessControl access, ref NativeGetterAccessor _Getter, ref NativeSetterAccessor _Setter) { if (name.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(name), "Cannot be null, empty, or only whitespace."); } if (attributes == V8PropertyAttributes.Undefined) { attributes = V8PropertyAttributes.None; } if (attributes < 0) { throw new InvalidOperationException("'attributes' has an invalid value."); } if (access < 0) { throw new InvalidOperationException("'access' has an invalid value."); } if (getter != null && _Getter == null) { _Getter = (_this, _name) => // (only need to set this once on first use) { try { return(getter != null?getter(_this, _name) : null); } catch (Exception ex) { return(engine.CreateError(Exceptions.GetFullErrorMessage(ex), JSValueType.ExecutionError)); } } } ; if (setter != null && _Setter == null) { _Setter = (_this, _name, _val) => // (only need to set this once on first use) { try { return(setter != null?setter(_this, _name, _val) : null); } catch (Exception ex) { return(engine.CreateError(Exceptions.GetFullErrorMessage(ex), JSValueType.ExecutionError)); } } } ; return(attributes); }