ArgumentsObject.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System;
  2. using System.Collections.Generic;
  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. using Jint.Runtime.Environments;
  9. namespace Jint.Native.Argument
  10. {
  11. /// <summary>
  12. /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.6
  13. /// </summary>
  14. public class ArgumentsInstance : ObjectInstance
  15. {
  16. public ArgumentsInstance(Engine engine) : base(engine)
  17. {
  18. // todo: complete implementation
  19. }
  20. public bool Strict { get; set; }
  21. public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, object[] args, EnvironmentRecord env, bool strict)
  22. {
  23. var len = args.Length;
  24. var obj = new ArgumentsInstance(engine);
  25. obj.Prototype = engine.Object.PrototypeObject;
  26. obj.Extensible = true;
  27. obj.FastAddProperty("length", len, true, false, true);
  28. obj.Strict = strict;
  29. var map = engine.Object.Construct(Arguments.Empty);
  30. var mappedNamed = new List<string>();
  31. var indx = len - 1;
  32. while (indx >= 0)
  33. {
  34. var indxStr = TypeConverter.ToString(indx);
  35. var val = args[indx];
  36. obj.FastAddProperty(indxStr, val, true, true, true);
  37. if (indx < names.Length)
  38. {
  39. var name = names[indx];
  40. if (!strict && !mappedNamed.Contains(name))
  41. {
  42. mappedNamed.Add(name);
  43. Func<object, object> g = n => env.GetBindingValue(name, false);
  44. var p = new Action<object, object>((n, o) => env.SetMutableBinding(name, o, true));
  45. map.DefineOwnProperty(indxStr, new ClrAccessDescriptor<object>(engine, g, p) { Configurable = true }, false);
  46. }
  47. }
  48. indx--;
  49. }
  50. // step 12
  51. if (mappedNamed.Count > 0)
  52. {
  53. obj.ParameterMap = map;
  54. }
  55. // step 13
  56. if (!strict)
  57. {
  58. obj.FastAddProperty("callee",func, true, false, true);
  59. }
  60. // step 14
  61. else
  62. {
  63. var thrower = engine.Function.ThrowTypeError;
  64. obj.DefineOwnProperty("caller", new AccessorDescriptor(thrower, thrower) { Enumerable = false, Configurable = false }, false);
  65. obj.DefineOwnProperty("callee", new AccessorDescriptor(thrower, thrower) { Enumerable = false, Configurable = false }, false);
  66. }
  67. return obj;
  68. }
  69. public ObjectInstance ParameterMap { get; set; }
  70. public override string Class
  71. {
  72. get
  73. {
  74. return "Arguments";
  75. }
  76. }
  77. public override PropertyDescriptor GetOwnProperty(string propertyName)
  78. {
  79. if (!Strict && ParameterMap != null)
  80. {
  81. var desc = base.GetOwnProperty(propertyName);
  82. if (desc == PropertyDescriptor.Undefined)
  83. {
  84. return desc;
  85. }
  86. var isMapped = ParameterMap.GetOwnProperty(propertyName);
  87. if (isMapped != PropertyDescriptor.Undefined)
  88. {
  89. desc.As<DataDescriptor>().Value = ParameterMap.Get(propertyName);
  90. }
  91. return desc;
  92. }
  93. return base.GetOwnProperty(propertyName);
  94. }
  95. public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
  96. {
  97. if (!Strict && ParameterMap != null)
  98. {
  99. var map = ParameterMap;
  100. var isMapped = map.GetOwnProperty(propertyName);
  101. var allowed = base.DefineOwnProperty(propertyName, desc, false);
  102. if (!allowed)
  103. {
  104. if (throwOnError)
  105. {
  106. throw new JavaScriptException(Engine.TypeError);
  107. }
  108. }
  109. if (isMapped != PropertyDescriptor.Undefined)
  110. {
  111. if (desc.IsAccessorDescriptor())
  112. {
  113. map.Delete(propertyName, false);
  114. }
  115. else
  116. {
  117. if (desc.As<DataDescriptor>().Value != null)
  118. {
  119. map.Put(propertyName, desc.As<DataDescriptor>().Value, throwOnError);
  120. }
  121. if (desc.As<DataDescriptor>().Writable.HasValue == false)
  122. {
  123. map.Delete(propertyName, false);
  124. }
  125. }
  126. }
  127. return true;
  128. }
  129. return base.DefineOwnProperty(propertyName, desc, throwOnError);
  130. }
  131. public override bool Delete(string propertyName, bool throwOnError)
  132. {
  133. if (!Strict && ParameterMap != null)
  134. {
  135. var map = ParameterMap;
  136. var isMapped = map.GetOwnProperty(propertyName);
  137. var result = base.Delete(propertyName, throwOnError);
  138. if (result && isMapped != PropertyDescriptor.Undefined)
  139. {
  140. map.Delete(propertyName, false);
  141. }
  142. return result;
  143. }
  144. return base.Delete(propertyName, throwOnError);
  145. }
  146. }
  147. }