123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- using Jint.Collections;
- using Jint.Native.Object;
- using Jint.Native.Symbol;
- using Jint.Runtime;
- using Jint.Runtime.Descriptors;
- using Jint.Runtime.Interop;
- namespace Jint.Native.Json
- {
- internal sealed class JsonInstance : ObjectInstance
- {
- private readonly Realm _realm;
- internal JsonInstance(
- Engine engine,
- Realm realm,
- ObjectPrototype objectPrototype)
- : base(engine)
- {
- _realm = realm;
- _prototype = objectPrototype;
- }
- protected override void Initialize()
- {
- var properties = new PropertyDictionary(2, checkExistingKeys: false)
- {
- #pragma warning disable 618
- ["parse"] = new PropertyDescriptor(new ClrFunction(Engine, "parse", Parse, 2, PropertyFlag.Configurable), true, false, true),
- ["stringify"] = new PropertyDescriptor(new ClrFunction(Engine, "stringify", Stringify, 3, PropertyFlag.Configurable), true, false, true)
- #pragma warning restore 618
- };
- SetProperties(properties);
- var symbols = new SymbolDictionary(1)
- {
- [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("JSON", false, false, true),
- };
- SetSymbols(symbols);
- }
- private static JsValue InternalizeJSONProperty(JsValue holder, JsValue name, ICallable reviver)
- {
- var temp = holder.Get(name);
- if (temp is ObjectInstance val)
- {
- if (val.IsArray())
- {
- var i = 0UL;
- var len = TypeConverter.ToLength(val.Get(CommonProperties.Length));
- while (i < len)
- {
- var prop = JsString.Create(i);
- var newElement = InternalizeJSONProperty(val, prop, reviver);
- if (newElement.IsUndefined())
- {
- val.Delete(prop);
- }
- else
- {
- val.CreateDataProperty(prop, newElement);
- }
- i = i + 1;
- }
- }
- else
- {
- var keys = val.EnumerableOwnProperties(EnumerableOwnPropertyNamesKind.Key);
- foreach (var p in keys)
- {
- var newElement = InternalizeJSONProperty(val, p, reviver);
- if (newElement.IsUndefined())
- {
- val.Delete(p);
- }
- else
- {
- val.CreateDataProperty(p, newElement);
- }
- }
- }
- }
- return reviver.Call(holder, new[] { name, temp });
- }
- /// <summary>
- /// https://tc39.es/ecma262/#sec-json.parse
- /// </summary>
- private JsValue Parse(JsValue thisObject, JsValue[] arguments)
- {
- var jsonString = TypeConverter.ToString(arguments.At(0));
- var reviver = arguments.At(1);
- var parser = new JsonParser(_engine);
- var unfiltered = parser.Parse(jsonString);
- if (reviver.IsCallable)
- {
- var root = _realm.Intrinsics.Object.Construct(Arguments.Empty);
- var rootName = JsString.Empty;
- root.CreateDataPropertyOrThrow(rootName, unfiltered);
- return InternalizeJSONProperty(root, rootName, (ICallable) reviver);
- }
- else
- {
- return unfiltered;
- }
- }
- private JsValue Stringify(JsValue thisObject, JsValue[] arguments)
- {
- var value = arguments.At(0);
- var replacer = arguments.At(1);
- var space = arguments.At(2);
- if (value.IsUndefined() && replacer.IsUndefined())
- {
- return Undefined;
- }
- var serializer = new JsonSerializer(_engine);
- return serializer.Serialize(value, replacer, space);
- }
- }
- }
|