public void SetProp(string ind, PropWrapper v) { if (this.Members.ContainsKey(ind)) { this.Members[ind] = v; } else { this.Members.Add(ind, v); } }
public virtual JSValue this[string ind] { get { PropWrapper r = this.getRef(ind, false); if (r != null) { return(r.Get(this)); } return(JSUndefined.Instance); } set { PropWrapper r = this.getRef(ind, true); if (r != null) { r.Set(this, value); } } }
internal PropWrapper getRef(string ind, bool ForSet) { PropWrapper r = this.GetOwnPropertyRef(ind); if (r != null) { return(r); } for (JSValue v = this.Prototype; v != null; v = v.Prototype) { r = v.GetOwnPropertyRef(ind); if (ForSet && (r is DataProperty)) { return(null); } if (r != null) { return(r); } } return(null); }
private void AddObjectProperties() { this.Global.SetDataProp("Object", this.ObjectCtor, false, false, false); this.ObjectCtor.SetDataProp("getPrototypeOf", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "getPrototypeOf argument not an object"); } JSValue r = arg.Prototype; if (r == null) { return(JSNull.Instance); } return(r); }, 1), true, false, true); this.ObjectCtor.SetDataProp("getOwnPropertyNames", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "getOwnPropertyNames argument not an object"); } IList <KeyValuePair <string, PropWrapper> > c = arg.GetOwnProperties(); List <JSValue> ar = new List <JSValue>(); foreach (KeyValuePair <string, PropWrapper> p in c) { if (p.Value.Enumerable) { ar.Add(p.Key); } } return(new JSArray(ar.ToArray())); }, 1), true, false, true); this.ObjectCtor.SetDataProp("create", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSValue arg = args[0]; if (!((arg is JSObject) || (arg is JSNull))) { throw new JSRuntimeException("TypeError", "invalid prototype passed to Object.create"); } if (arg is JSNull) { arg = null; } JSObject obj = new JSObject(arg); if (args.Count > 1) { throw new NotImplementedException(); } return(obj); }, 1), true, false, true); this.ObjectCtor.SetDataProp("defineProperty", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject O = args[0] as JSObject; if (O == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.defineProperty"); } string P = args[1].StringValue(); JSObject desc = args[2].ToJSObject(); UpdatePropertyDescriptor(O, P, desc); return(O); }, 3), true, false, true); this.ObjectCtor.SetDataProp("defineProperties", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { throw new Exception(); }), true, false, true); this.ObjectCtor.SetDataProp("seal", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.seal"); } foreach (KeyValuePair <string, PropWrapper> p in arg.GetOwnProperties()) { p.Value.Configurable = false; } arg.IsExtensible = false; return(arg); }, 1), true, false, true); this.ObjectCtor.SetDataProp("freeze", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.freeze"); } foreach (KeyValuePair <string, PropWrapper> p in arg.GetOwnProperties()) { if (p.Value is DataProperty) { p.Value.Writable = false; } p.Value.Configurable = false; } arg.IsExtensible = false; return(arg); }, 1), true, false, true); this.ObjectCtor.SetDataProp("preventExtensions", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.preventExtensions"); } arg.IsExtensible = false; return(arg); }, 1), true, false, true); this.ObjectCtor.SetDataProp("isSealed", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.isSealed"); } if (arg.IsExtensible) { return(JSBool.False); } foreach (KeyValuePair <string, PropWrapper> p in arg.GetOwnProperties()) { if (p.Value.Configurable) { return(JSBool.False); } } return(JSBool.True); }, 1), true, false, true); this.ObjectCtor.SetDataProp("isFrozen", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.isFrozen"); } if (arg.IsExtensible) { return(JSBool.False); } foreach (KeyValuePair <string, PropWrapper> p in arg.GetOwnProperties()) { if ((p.Value is DataProperty) && p.Value.Writable) { return(JSBool.False); } if (p.Value.Configurable) { return(JSBool.False); } } return(JSBool.True); }, 1), true, false, true); this.ObjectCtor.SetDataProp("isExtensible", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.isExtensible"); } return(arg.IsExtensible); }, 1), true, false, true); this.ObjectCtor.SetDataProp("keys", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSObject arg = args[0] as JSObject; if (arg == null) { throw new JSRuntimeException("TypeError", "invalid argument passed to Object.keys"); } IList <KeyValuePair <string, PropWrapper> > ar = arg.GetOwnProperties(); List <JSValue> ar2 = new List <JSValue>(); for (int i = 0; i < ar.Count; i++) { KeyValuePair <string, PropWrapper> p = ar[i]; if (p.Value.Enumerable) { ar2.Add(p.Key); } } return(new JSArray(ar2.ToArray())); }, 1), true, false, true); this.ObjectPrototype.SetDataProp("toString", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { return("[object " + ThisObj.ClassString + "]"); }), true, false, true); this.ObjectPrototype.SetDataProp("toLocaleString", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { return(((JSFunctionBase)ThisObj.ToJSObject()["toString"]).Call(Scope, ThisObj, args)); }), true, false, true); this.ObjectPrototype.SetDataProp("valueOf", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { return(ThisObj); }), true, false, true); this.ObjectPrototype.SetDataProp("hasOwnProperty", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { return(ThisObj.HasOwnProperty(args[0].StringValue())); }, 1), true, false, true); this.ObjectPrototype.SetDataProp("isPrototypeOf", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { JSValue v = args[0]; while (true) { v = v.Prototype; if (v == null) { return(JSBool.False); } if (v == ThisObj) { return(JSBool.True); } } }, 1), true, false, true); this.ObjectPrototype.SetDataProp("propertyIsEnumerable", new JSDelegateWrapper(delegate(JSContext Scope, JSValue ThisObj, JSArgs args, bool AsConstructor) { string v = args[0].StringValue(); PropWrapper r = ThisObj.ToJSObject().GetOwnPropertyRef(v); if (r == null) { return(JSBool.False); } return(r.Enumerable); }, 1), true, false, true); }
private static void UpdatePropertyDescriptor(JSObject O, string P, JSObject desc) { JSValue tmp; JSValue value = JSUndefined.Instance; JSFunctionBase getter = null; JSFunctionBase setter = null; bool enumerable = true; bool configurable = true; bool writable = true; bool hasValue = false; bool hasGet = false; bool hasSet = false; bool hasEnumerable = false; bool hasConfigurable = false; bool hasWritable = false; if (desc.TryGetPropertyValue("enumerable", out tmp)) { enumerable = tmp.BoolValue(); hasEnumerable = true; } if (desc.TryGetPropertyValue("configurable", out tmp)) { configurable = tmp.BoolValue(); hasConfigurable = true; } if (desc.TryGetPropertyValue("value", out tmp)) { value = tmp; hasValue = true; } if (desc.TryGetPropertyValue("writable", out tmp)) { writable = tmp.BoolValue(); hasWritable = true; } if (desc.TryGetPropertyValue("get", out tmp)) { if (tmp is JSUndefined) { getter = null; } else { if (!(tmp is JSFunctionBase)) { throw new JSRuntimeException("TypeError", "invalid 'get' property in property descriptor"); } getter = (JSFunctionBase)tmp; } hasGet = true; } if (desc.TryGetPropertyValue("set", out tmp)) { if (tmp is JSUndefined) { setter = null; } else { if (!(tmp is JSFunctionBase)) { throw new JSRuntimeException("TypeError", "invalid 'set' property in property descriptor"); } setter = (JSFunctionBase)tmp; } hasSet = true; } if (hasValue || hasGet || hasSet || hasEnumerable || hasConfigurable || hasWritable) { PropWrapper newProp; bool bIsAccessor; if (!(hasGet || hasSet)) { bIsAccessor = false; } else { if (hasValue || hasWritable) { throw new JSRuntimeException("TypeError", "property descriptor contained values for both data and accessor"); } bIsAccessor = true; } PropWrapper oldProp = O.GetOwnPropertyRef(P); if (oldProp == null) { if (!O.IsExtensible) { throw new JSRuntimeException("TypeError", "object is not extensible"); } if (bIsAccessor) { newProp = new AccessorProperty(getter, setter, writable, enumerable, configurable); } else { newProp = new DataProperty(value, writable, enumerable, configurable); } } else { if (oldProp is DataProperty) { DataProperty _o = oldProp as DataProperty; if ((((!hasValue || JSValue.JSEqualsExact(value, _o.Value)) && (!hasEnumerable || (writable == oldProp.Writable))) && (!hasConfigurable || (enumerable == oldProp.Enumerable))) && (!hasWritable || (configurable == oldProp.Configurable))) { return; } } else if (oldProp is AccessorProperty) { AccessorProperty _o = oldProp as AccessorProperty; if ((((!hasEnumerable || (writable == oldProp.Writable)) && (!hasConfigurable || (enumerable == oldProp.Enumerable))) && (!hasGet || (getter == _o.Getter))) && (!hasSet || (setter == _o.Setter))) { return; } } if (!oldProp.Configurable) { throw new JSRuntimeException("TypeError", "property is not configurable"); } if ((bIsAccessor && (oldProp is AccessorProperty)) || (!bIsAccessor && (oldProp is DataProperty))) { newProp = oldProp; } else if (bIsAccessor) { newProp = new AccessorProperty(getter, setter); } else { newProp = new DataProperty(value); } if (hasConfigurable) { newProp.Configurable = configurable; } if (hasEnumerable) { newProp.Enumerable = enumerable; } if (bIsAccessor) { if (hasGet) { ((AccessorProperty)newProp).Getter = getter; } if (hasSet) { ((AccessorProperty)newProp).Setter = setter; } } else { if (hasWritable) { ((DataProperty)newProp).Value = value; } if (hasValue) { newProp.Set(O, value); } } } O.SetProp(P, newProp); } }