JsonInstance.cs 4.9 KB

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