JsonInstance.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using Jint.Native.Object;
  2. using Jint.Runtime;
  3. using Jint.Runtime.Descriptors;
  4. using Jint.Runtime.Interop;
  5. namespace Jint.Native.Json
  6. {
  7. public sealed class JsonInstance : ObjectInstance
  8. {
  9. private readonly Engine _engine;
  10. private JsValue _reviver;
  11. private JsonInstance(Engine engine)
  12. : base(engine)
  13. {
  14. _engine = engine;
  15. Extensible = true;
  16. }
  17. public override string Class
  18. {
  19. get
  20. {
  21. return "JSON";
  22. }
  23. }
  24. public static JsonInstance CreateJsonObject(Engine engine)
  25. {
  26. var json = new JsonInstance(engine);
  27. json.Prototype = engine.Object.PrototypeObject;
  28. return json;
  29. }
  30. public void Configure()
  31. {
  32. FastAddProperty("parse", new ClrFunctionInstance(Engine, Parse, 2), true, false, true);
  33. FastAddProperty("stringify", new ClrFunctionInstance(Engine, Stringify, 3), true, false, true);
  34. }
  35. private JsValue AbstractWalkOperation(ObjectInstance thisObject, string prop)
  36. {
  37. JsValue value = thisObject.Get(prop);
  38. if (value.IsObject())
  39. {
  40. var valueAsObject = value.AsObject();
  41. if (valueAsObject.Class == "Array")
  42. {
  43. var valAsArray = value.AsArray();
  44. var i = 0;
  45. var arrLen = valAsArray.GetLength();
  46. while (i < arrLen)
  47. {
  48. var newValue = AbstractWalkOperation(valAsArray, TypeConverter.ToString(i));
  49. if (newValue.IsUndefined())
  50. {
  51. valAsArray.Delete(TypeConverter.ToString(i), false);
  52. }
  53. else
  54. {
  55. valAsArray.DefineOwnProperty
  56. (
  57. TypeConverter.ToString(i),
  58. new PropertyDescriptor
  59. (
  60. value: newValue,
  61. writable: true,
  62. enumerable: true,
  63. configurable: true
  64. ),
  65. false
  66. );
  67. }
  68. i = i + 1;
  69. }
  70. }
  71. else
  72. {
  73. var keys = valueAsObject.GetOwnProperties();
  74. foreach (var p in keys)
  75. {
  76. var newElement = AbstractWalkOperation(valueAsObject, p.Key);
  77. if (newElement.IsUndefined())
  78. {
  79. valueAsObject.Delete(p.Key, false);
  80. }
  81. else
  82. {
  83. valueAsObject.DefineOwnProperty(
  84. p.Key,
  85. new PropertyDescriptor
  86. (
  87. value: newElement,
  88. writable: true,
  89. enumerable: true,
  90. configurable: true
  91. ),
  92. false
  93. );
  94. }
  95. }
  96. }
  97. }
  98. return _reviver.Invoke(thisObject, new JsValue[] { prop, value });
  99. }
  100. public JsValue Parse(JsValue thisObject, JsValue[] arguments)
  101. {
  102. var parser = new JsonParser(_engine);
  103. var res = parser.Parse(TypeConverter.ToString(arguments[0]));
  104. if (arguments.Length > 1)
  105. {
  106. this._reviver = arguments[1];
  107. ObjectInstance revRes = ObjectConstructor.CreateObjectConstructor(_engine).Construct(Arguments.Empty);
  108. revRes.DefineOwnProperty(
  109. "",
  110. new PropertyDescriptor(
  111. value: res,
  112. writable: true,
  113. enumerable: true,
  114. configurable: true
  115. ),
  116. false
  117. );
  118. return AbstractWalkOperation(revRes, "");
  119. }
  120. return res;
  121. }
  122. public JsValue Stringify(JsValue thisObject, JsValue[] arguments)
  123. {
  124. JsValue
  125. value = Undefined,
  126. replacer = Undefined,
  127. space = Undefined;
  128. if (arguments.Length > 2)
  129. {
  130. space = arguments[2];
  131. }
  132. if (arguments.Length > 1)
  133. {
  134. replacer = arguments[1];
  135. }
  136. if (arguments.Length > 0)
  137. {
  138. value = arguments[0];
  139. }
  140. var serializer = new JsonSerializer(_engine);
  141. if (ReferenceEquals(value, Undefined) && ReferenceEquals(replacer, Undefined)) {
  142. return Undefined;
  143. }
  144. return serializer.Serialize(value, replacer, space);
  145. }
  146. }
  147. }