/// <summary> /// Depending on the syntax used in the Javascript function, the object /// returned by Jint can be either a Dictionary or a /// Jint.Native.ObjectInstance, each with a different parsing logic. /// </summary> private Dictionary <string, object> JsValueToDictionary(JsValue data) { var result = new Dictionary <string, object>(); if (data == null) { return(result); } try { // Manage output as a Dictionary result = data.ToObject() as Dictionary <string, object>; if (result != null) { this.log.Debug("JS function output", () => new { Type = "Dictionary", data.GetType().FullName, result }); return(result); } // Manage output as a Jint.Native.ObjectInstance result = new Dictionary <string, object>(); var properties = data.AsObject().GetOwnProperties().ToArray(); foreach (KeyValuePair <string, PropertyDescriptor> p in properties) { result.Add(p.Key, p.Value.Value.ToObject()); } this.log.Debug("JS function output", () => new { Type = "ObjectInstance", data.GetType().FullName, result }); return(result); } catch (Exception e) { this.log.Error("JsValue parsing failure", () => new { e.Message, e.GetType().FullName }); return(new Dictionary <string, object>()); } }
/// Implementation from ObjectInstance official specs as the one /// in ObjectInstance is optimized for the general case and wouldn't work /// for arrays public override void Put(string propertyName, JsValue value, bool throwOnError) { if (!CanPut(propertyName)) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return; } if (InternalArray != null) { int ind; if (int.TryParse(propertyName, out ind)) { object val; switch (value.Type) { case Types.Undefined: val = null; break; case Types.Null: val = null; break; case Types.Boolean: val = value.AsBoolean(); break; case Types.String: val = value.AsString(); break; case Types.Number: val = value.AsNumber(); break; case Types.Object: val = value; var ow = ((JsValue)val).AsObject() as ObjectWrapper; if (ow != null) { val = ow.Target; } break; default: throw new ArgumentOutOfRangeException(); } if (ind >= InternalArray.Count) { for (int i = InternalArray.Count; i <= ind; i++) { if (val != null) InternalArray.Add(GetDefault(val.GetType())); else InternalArray.Add(null); } } InternalArray[ind] = val; } } var ownDesc = GetOwnProperty(propertyName); if (ownDesc.IsDataDescriptor()) { var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable: null, configurable: null); DefineOwnProperty(propertyName, valueDesc, throwOnError); return; } // property is an accessor or inherited var desc = GetProperty(propertyName); if (desc.IsAccessorDescriptor()) { var setter = desc.Set.Value.TryCast<ICallable>(); setter.Call(new JsValue(this), new[] { value }); } else { var newDesc = new PropertyDescriptor(value, true, true, true); DefineOwnProperty(propertyName, newDesc, throwOnError); } }
/// Implementation from ObjectInstance official specs as the one /// in ObjectInstance is optimized for the general case and wouldn't work /// for arrays public override void Put(string propertyName, JsValue value, bool throwOnError) { if (!CanPut(propertyName)) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return; } if (InternalArray != null) { int ind; if (int.TryParse(propertyName, out ind)) { object val; switch (value.Type) { case Types.Undefined: val = null; break; case Types.Null: val = null; break; case Types.Boolean: val = value.AsBoolean(); break; case Types.String: val = value.AsString(); break; case Types.Number: val = value.AsNumber(); break; case Types.Object: val = value; var ow = ((JsValue)val).AsObject() as ObjectWrapper; if (ow != null) { val = ow.Target; } break; default: throw new ArgumentOutOfRangeException(); } if (ind >= InternalArray.Count) { for (int i = InternalArray.Count; i <= ind; i++) { if (val != null) { InternalArray.Add(GetDefault(val.GetType())); } else { InternalArray.Add(null); } } } InternalArray[ind] = val; } } var ownDesc = GetOwnProperty(propertyName); if (ownDesc.IsDataDescriptor()) { var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable: null, configurable: null); DefineOwnProperty(propertyName, valueDesc, throwOnError); return; } // property is an accessor or inherited var desc = GetProperty(propertyName); if (desc.IsAccessorDescriptor()) { var setter = desc.Set.Value.TryCast <ICallable>(); setter.Call(new JsValue(this), new[] { value }); } else { var newDesc = new PropertyDescriptor(value, true, true, true); DefineOwnProperty(propertyName, newDesc, throwOnError); } }