// used by InitializeProjectionForType private JavaScriptObject CreateObjectFor(JavaScriptEngine engine, JavaScriptProjection baseTypeProjection) { if (baseTypeProjection != null) { // todo: revisit to see if there is a better way to do this // Can probably get // ((engine.GlobalObject.GetPropertyByName("Object") as JavaScriptObject).GetPropertyByName("create") as JavaScriptFunction).Invoke(baseTypeProjection.Prototype) // but this is so much clearer dynamic global = engine.GlobalObject; JavaScriptObject result = global.Object.create(baseTypeProjection.Prototype); return(result); } else { return(engine.CreateObject()); } }
private void ProjectProperties(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable<PropertyInfo> properties) { foreach (var prop in properties) { if (prop.GetIndexParameters().Length > 0) throw new NotSupportedException("Index properties not supported for projecting CLR to JavaScript objects."); JavaScriptFunction jsGet = null, jsSet = null; if (prop.GetMethod != null) { jsGet = engine.CreateFunction((eng, ctor, thisObj, args) => { var @this = thisObj as JavaScriptObject; if (@this == null) { eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context.")); return eng.UndefinedValue; } try { return FromObject(prop.GetValue(@this.ExternalObject)); } catch (Exception ex) { eng.SetException(FromObject(ex)); return eng.UndefinedValue; } }, owningTypeName + "." + prop.Name + ".get"); } if (prop.SetMethod != null) { jsSet = engine.CreateFunction((eng, ctor, thisObj, args) => { var @this = thisObj as JavaScriptObject; if (@this == null) { eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context.")); return eng.UndefinedValue; } try { var val = ToObject(args.First()); if (prop.PropertyType == typeof(int)) { val = (int)(double)val; } prop.SetValue(@this.ExternalObject, val); return eng.UndefinedValue; } catch (Exception ex) { eng.SetException(FromObject(ex)); return eng.UndefinedValue; } }, owningTypeName + "." + prop.Name + ".set"); } var descriptor = engine.CreateObject(); if (jsGet != null) descriptor.SetPropertyByName("get", jsGet); if (jsSet != null) descriptor.SetPropertyByName("set", jsSet); descriptor.SetPropertyByName("enumerable", engine.TrueValue); target.DefineProperty(prop.Name, descriptor); } }
// used by InitializeProjectionForType private JavaScriptObject CreateObjectFor(JavaScriptEngine engine, JavaScriptProjection baseTypeProjection) { if (baseTypeProjection != null) { // todo: revisit to see if there is a better way to do this // Can probably get // ((engine.GlobalObject.GetPropertyByName("Object") as JavaScriptObject).GetPropertyByName("create") as JavaScriptFunction).Invoke(baseTypeProjection.Prototype) // but this is so much clearer dynamic global = engine.GlobalObject; JavaScriptObject result = global.Object.create(baseTypeProjection.Prototype); return result; } else { return engine.CreateObject(); } }
private void ProjectProperties(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable <PropertyInfo> properties) { foreach (var prop in properties) { if (prop.GetIndexParameters().Length > 0) { throw new NotSupportedException("Index properties not supported for projecting CLR to JavaScript objects."); } JavaScriptFunction jsGet = null, jsSet = null; if (prop.GetMethod != null) { jsGet = engine.CreateFunction((eng, ctor, thisObj, args) => { var @this = thisObj as JavaScriptObject; if (@this == null) { eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context.")); return(eng.UndefinedValue); } object external = null; if (!prop.GetMethod.IsStatic) { external = @this.ExternalObject; if (external == null) { external = @this.Prototype.ExternalObject; } if (external == null) { throw new Exception("this object not found for method invocation. Perhaps it has been garbage collected."); } } try { return(FromObject(prop.GetValue(external))); } catch (Exception ex) { eng.SetException(FromObject(ex), ex); return(eng.UndefinedValue); } }, owningTypeName + "." + prop.Name + ".get"); } if (prop.SetMethod != null) { jsSet = engine.CreateFunction((eng, ctor, thisObj, args) => { var @this = thisObj as JavaScriptObject; if (@this == null) { eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context.")); return(eng.UndefinedValue); } try { var val = ToObject(args.First()); if (prop.PropertyType == typeof(int)) { val = (int)(double)val; } var obj = @this.ExternalObject; if (obj == null && @this.Prototype.ExternalObject == engine.GlobalObject.Prototype.ExternalObject) { obj = @this.Prototype.ExternalObject; } prop.SetValue(obj, val); return(eng.UndefinedValue); } catch (Exception ex) { eng.SetException(FromObject(ex), ex); return(eng.UndefinedValue); } }, owningTypeName + "." + prop.Name + ".set"); } var descriptor = engine.CreateObject(); if (jsGet != null) { descriptor.SetPropertyByName("get", jsGet); } if (jsSet != null) { descriptor.SetPropertyByName("set", jsSet); } descriptor.SetPropertyByName("enumerable", engine.TrueValue); target.DefineProperty(prop.Name, descriptor); } }