ArrayConstructor.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System;
  2. using System.Linq;
  3. using Jint.Native.Function;
  4. using Jint.Native.Object;
  5. using Jint.Runtime;
  6. using Jint.Runtime.Descriptors;
  7. using Jint.Runtime.Descriptors.Specialized;
  8. namespace Jint.Native.Array
  9. {
  10. public sealed class ArrayConstructor : FunctionInstance, IConstructor
  11. {
  12. private readonly Engine _engine;
  13. public ArrayConstructor(Engine engine) : base(engine, new ObjectInstance(engine, engine.RootFunction), null, null, false)
  14. {
  15. _engine = engine;
  16. // the constructor is the function constructor of an object
  17. Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
  18. Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
  19. // Array prototype functions
  20. Prototype.DefineOwnProperty("push", new ClrDataDescriptor<ArrayInstance, object>(engine, Push), false);
  21. Prototype.DefineOwnProperty("pop", new ClrDataDescriptor<ArrayInstance, object>(engine, Pop), false);
  22. }
  23. public override object Call(object thisObject, object[] arguments)
  24. {
  25. return Construct(arguments);
  26. }
  27. public ObjectInstance Construct(object[] arguments)
  28. {
  29. var instance = new ArrayInstance(_engine, Prototype);
  30. if (arguments.Length == 1 && TypeConverter.GetType(arguments[0]) == TypeCode.Double)
  31. {
  32. var length = TypeConverter.ToNumber(arguments[0]);
  33. instance.FastAddProperty("length", length, true, false, true);
  34. }
  35. else
  36. {
  37. instance.FastAddProperty("length", 0, true, false, true);
  38. Push(instance, arguments);
  39. }
  40. return instance;
  41. }
  42. private object Push(object thisObject, object[] arguments)
  43. {
  44. var o = TypeConverter.ToObject(_engine, thisObject);
  45. var lenVal = o.Get("length");
  46. var n = TypeConverter.ToUint32(lenVal);
  47. foreach (var e in arguments)
  48. {
  49. o.Put(TypeConverter.ToString(n), e, true);
  50. n++;
  51. }
  52. o.Put("length", n, true);
  53. return n;
  54. }
  55. private object Pop(object thisObject, object[] arguments)
  56. {
  57. var o = TypeConverter.ToObject(_engine, thisObject);
  58. var lenVal = o.Get("length");
  59. var len = TypeConverter.ToUint32(lenVal);
  60. if (len == 0)
  61. {
  62. o.Put("length", 0, true);
  63. return Undefined.Instance;
  64. }
  65. else
  66. {
  67. var indx = TypeConverter.ToString(len - 1);
  68. var element = o.Get(indx);
  69. o.Delete(indx, true);
  70. o.Put("length", indx, true);
  71. return element;
  72. }
  73. }
  74. }
  75. }