|
@@ -1,4 +1,6 @@
|
|
using System;
|
|
using System;
|
|
|
|
+using System.Collections.Generic;
|
|
|
|
+using System.Linq;
|
|
using Jint.Native.Function;
|
|
using Jint.Native.Function;
|
|
using Jint.Runtime;
|
|
using Jint.Runtime;
|
|
using Jint.Runtime.Descriptors;
|
|
using Jint.Runtime.Descriptors;
|
|
@@ -101,22 +103,69 @@ namespace Jint.Native.Object
|
|
|
|
|
|
public object GetPrototypeOf(object thisObject, object[] arguments)
|
|
public object GetPrototypeOf(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ return o.Prototype ?? Null.Instance;
|
|
}
|
|
}
|
|
|
|
|
|
public object GetOwnPropertyDescriptor(object thisObject, object[] arguments)
|
|
public object GetOwnPropertyDescriptor(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ var p = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
|
|
|
|
+ var name = TypeConverter.ToString(p);
|
|
|
|
+
|
|
|
|
+ var desc = o.GetOwnProperty(name);
|
|
|
|
+ return PropertyDescriptor.FromPropertyDescriptor(Engine, desc);
|
|
}
|
|
}
|
|
|
|
|
|
public object GetOwnPropertyNames(object thisObject, object[] arguments)
|
|
public object GetOwnPropertyNames(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ var array = Engine.Array.Construct(Arguments.Empty);
|
|
|
|
+ var n = 0;
|
|
|
|
+ foreach (var p in o.Properties)
|
|
|
|
+ {
|
|
|
|
+ array.DefineOwnProperty(n.ToString(), new DataDescriptor(p.Key) { Writable = true, Enumerable = true, Configurable = true }, false);
|
|
|
|
+ n++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return array;
|
|
}
|
|
}
|
|
|
|
|
|
public object Create(object thisObject, object[] arguments)
|
|
public object Create(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object && thisObject != Null.Instance)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var obj = Engine.Object.Construct(Arguments.Empty);
|
|
|
|
+ obj.Prototype = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ var properties = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
|
|
|
|
+ if (properties != Undefined.Instance)
|
|
|
|
+ {
|
|
|
|
+ DefineProperties(obj, new [] {properties});
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return obj;
|
|
}
|
|
}
|
|
|
|
|
|
public object DefineProperty(object thisObject, object[] arguments)
|
|
public object DefineProperty(object thisObject, object[] arguments)
|
|
@@ -143,42 +192,187 @@ namespace Jint.Native.Object
|
|
|
|
|
|
public object DefineProperties(object thisObject, object[] arguments)
|
|
public object DefineProperties(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ var properties = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
|
|
|
|
+ var props = TypeConverter.ToObject(Engine, properties);
|
|
|
|
+ var names = props.Properties.Keys;
|
|
|
|
+ var descriptors = new List<KeyValuePair<string, PropertyDescriptor>>();
|
|
|
|
+ foreach (var p in names)
|
|
|
|
+ {
|
|
|
|
+ var descObj = props.Get(p);
|
|
|
|
+ var desc = PropertyDescriptor.ToPropertyDescriptor(Engine, descObj);
|
|
|
|
+ descriptors.Add(new KeyValuePair<string, PropertyDescriptor>(p, desc));
|
|
|
|
+ }
|
|
|
|
+ foreach (var pair in descriptors)
|
|
|
|
+ {
|
|
|
|
+ o.DefineOwnProperty(pair.Key, pair.Value, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return o;
|
|
}
|
|
}
|
|
|
|
|
|
public object Seal(object thisObject, object[] arguments)
|
|
public object Seal(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ foreach (var prop in o.Properties)
|
|
|
|
+ {
|
|
|
|
+ if (prop.Value.Configurable)
|
|
|
|
+ {
|
|
|
|
+ prop.Value.Configurable = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o.DefineOwnProperty(prop.Key, prop.Value, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o.Extensible = false;
|
|
|
|
+
|
|
|
|
+ return o;
|
|
}
|
|
}
|
|
|
|
|
|
public object Freeze(object thisObject, object[] arguments)
|
|
public object Freeze(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ foreach (var prop in o.Properties)
|
|
|
|
+ {
|
|
|
|
+ if (prop.Value.IsDataDescriptor())
|
|
|
|
+ {
|
|
|
|
+ var datadesc = prop.Value.As<DataDescriptor>();
|
|
|
|
+ if (datadesc.Writable)
|
|
|
|
+ {
|
|
|
|
+ datadesc.Writable = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (prop.Value.Configurable)
|
|
|
|
+ {
|
|
|
|
+ prop.Value.Configurable = false;
|
|
|
|
+ }
|
|
|
|
+ o.DefineOwnProperty(prop.Key, prop.Value, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o.Extensible = false;
|
|
|
|
+
|
|
|
|
+ return o;
|
|
}
|
|
}
|
|
|
|
|
|
public object PreventExtensions(object thisObject, object[] arguments)
|
|
public object PreventExtensions(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ o.Extensible = false;
|
|
|
|
+
|
|
|
|
+ return o;
|
|
}
|
|
}
|
|
|
|
|
|
public object IsSealed(object thisObject, object[] arguments)
|
|
public object IsSealed(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ foreach (var prop in o.Properties)
|
|
|
|
+ {
|
|
|
|
+ if (prop.Value.Configurable)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (o.Extensible)
|
|
|
|
+ {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
public object IsFrozen(object thisObject, object[] arguments)
|
|
public object IsFrozen(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ foreach (var prop in o.Properties)
|
|
|
|
+ {
|
|
|
|
+ if (prop.Value.IsDataDescriptor())
|
|
|
|
+ {
|
|
|
|
+ if (prop.Value.As<DataDescriptor>().Writable)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (prop.Value.Configurable)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (o.Extensible)
|
|
|
|
+ {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
public object IsExtensible(object thisObject, object[] arguments)
|
|
public object IsExtensible(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ return o.Extensible;
|
|
}
|
|
}
|
|
|
|
|
|
public object Keys(object thisObject, object[] arguments)
|
|
public object Keys(object thisObject, object[] arguments)
|
|
{
|
|
{
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
+ if (TypeConverter.GetType(thisObject) != TypeCode.Object)
|
|
|
|
+ {
|
|
|
|
+ throw new JavaScriptException(Engine.TypeError);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var o = thisObject as ObjectInstance;
|
|
|
|
+
|
|
|
|
+ var n = o.Properties.Values.Count(x => x.Enumerable);
|
|
|
|
+ var array = Engine.Array.Construct(new object[] {n});
|
|
|
|
+ var index = 0;
|
|
|
|
+ foreach (var prop in o.Properties.Where(x => x.Value.Enumerable))
|
|
|
|
+ {
|
|
|
|
+ array.DefineOwnProperty(index.ToString(), new DataDescriptor(prop.Key) { Writable = true, Enumerable = true, Configurable = true }, false);
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+ return array;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|