JsonInstance.cs 4.9 KB

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