using Jint.Collections; using Jint.Runtime; using Jint.Runtime.Descriptors; using Jint.Runtime.Interop; namespace Jint.Native.Object { public sealed class ObjectPrototype : ObjectInstance { private ObjectConstructor _objectConstructor; private ObjectPrototype(Engine engine) : base(engine) { } public static ObjectPrototype CreatePrototypeObject(Engine engine, ObjectConstructor objectConstructor) { var obj = new ObjectPrototype(engine) { Extensible = true, _objectConstructor = objectConstructor }; return obj; } protected override void Initialize() { _properties = new StringDictionarySlim(8) { ["constructor"] = new PropertyDescriptor(_objectConstructor, true, false, true), ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToObjectString), true, false, true), ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString), true, false, true), ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOF", ValueOf), true, false, true), ["hasOwnProperty"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "hasOwnProperty", HasOwnProperty, 1), true, false, true), ["isPrototypeOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isPrototypeOf", IsPrototypeOf, 1), true, false, true), ["propertyIsEnumerable"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "propertyIsEnumerable", PropertyIsEnumerable, 1), true, false, true) }; } private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments) { var p = TypeConverter.ToPropertyKey(arguments[0]); var o = TypeConverter.ToObject(Engine, thisObject); var desc = o.GetOwnProperty(p); if (desc == PropertyDescriptor.Undefined) { return false; } return desc.Enumerable; } private JsValue ValueOf(JsValue thisObject, JsValue[] arguments) { var o = TypeConverter.ToObject(Engine, thisObject); return o; } private JsValue IsPrototypeOf(JsValue thisObject, JsValue[] arguments) { var arg = arguments[0]; if (!arg.IsObject()) { return false; } var v = arg.AsObject(); var o = TypeConverter.ToObject(Engine, thisObject); while (true) { v = v.Prototype; if (ReferenceEquals(v, null)) { return false; } if (o == v) { return true; } } } private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments) { var o = TypeConverter.ToObject(Engine, thisObject); var toString = o.Get("toString").TryCast(x => { ExceptionHelper.ThrowTypeError(Engine); }); return toString.Call(o, Arguments.Empty); } /// /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.2 /// /// /// /// public JsValue ToObjectString(JsValue thisObject, JsValue[] arguments) { if (thisObject.IsUndefined()) { return "[object Undefined]"; } if (thisObject.IsNull()) { return "[object Null]"; } var o = TypeConverter.ToObject(Engine, thisObject); return "[object " + o.Class + "]"; } /// /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.5 /// public JsValue HasOwnProperty(JsValue thisObject, JsValue[] arguments) { var p = TypeConverter.ToPropertyKey(arguments[0]); var o = TypeConverter.ToObject(Engine, thisObject); var desc = o.GetOwnProperty(p); return desc != PropertyDescriptor.Undefined; } } }