// Return true if this JSValue is strictly equal to JSValue after they are converted to the same type.
        //
        // Null is not converted to any other type before comparison.
        // Object and Array types are converted first to a String type using AsString() before comparing
        // with other types, and then we apply the same rules as for the String type.
        // String is converted to Double before comparing with Boolean, Int64, or Double.
        // Boolean is converted to 1.0 and +0.0 when comparing with String, Int64, or Double.
        // Int64 is converted to Double before comparing with other types.
        //
        // The behavior is similar to JavaScript == operator except for Object and Array for which
        // this functions does a deep structured comparison using JSEquals instead
        // of pointer equality.
        public bool JSEquals(JSValue other)
        {
            if (Type == other.Type)
            {
                switch (Type)
                {
                case JSValueType.Object:
                    return(JSValueObject.JSEquals(ObjectValue, other.ObjectValue));

                case JSValueType.Array:
                    return(JSValueArray.JSEquals(ArrayValue, other.ArrayValue));

                default:
                    return(Equals(other));
                }
            }
            else if (Type == JSValueType.Null || other.Type == JSValueType.Null)
            {
                return(false);
            }

            // If one of the types Boolean, Int64, or Double, then compare as Numbers,
            // otherwise compare as strings.
            JSValueType greatestType = Type > other.Type ? Type : other.Type;

            if (greatestType >= JSValueType.Boolean)
            {
                return(AsJSNumber() == other.AsJSNumber());
            }
            else
            {
                return(AsJSString() == other.AsJSString());
            }
        }
        // Return true if this JSValue is strictly equal to JSValue.
        // Compared values must have the same type and value.
        //
        // The behavior is similar to JavaScript === operator except for Object and Array where
        // this functions does a deep structured comparison instead of pointer equality.
        public bool Equals(JSValue other)
        {
            if (Type != other.Type)
            {
                return(false);
            }

            switch (Type)
            {
            case JSValueType.Null: return(true);

            case JSValueType.Object: return(JSValueObject.Equals(ObjectValue, other.ObjectValue));

            case JSValueType.Array: return(JSValueArray.Equals(ArrayValue, other.ArrayValue));

            case JSValueType.String: return(StringValue == other.StringValue);

            case JSValueType.Boolean: return(BooleanValue == other.BooleanValue);

            case JSValueType.Int64: return(Int64Value == other.Int64Value);

            case JSValueType.Double: return(DoubleValue == other.DoubleValue);

            default: return(false);
            }
        }
        public static JSValueArray CopyFrom(IReadOnlyList <JSValue> other)
        {
            JSValueArray arr = new JSValueArray();

            foreach (var item in other)
            {
                arr.Add(item);
            }

            return(arr);
        }
        private static JSValueArray InternalReadArrayFrom(IJSValueReader reader)
        {
            var jsArray = new JSValueArray();

            while (reader.GetNextArrayItem())
            {
                jsArray.Add(InternalReadFrom(reader));
            }

            return(jsArray);
        }
        // Create JSValueArray from IJSValueReader.
        public static JSValueArray ReadArrayFrom(IJSValueReader reader)
        {
            if (reader.ValueType == JSValueType.Array)
            {
                if (reader is IJSValueTreeReader treeReader)
                {
                    return(JSValueArray.CopyFrom(treeReader.Current.ArrayValue));
                }

                return(InternalReadArrayFrom(reader));
            }

            return(new JSValueArray());
        }
 // Return true if this JSValueArray is strictly equal to 'other'.
 public bool Equals(JSValueArray other)
 {
     return(Equals(this as IReadOnlyList <JSValue>, other as IReadOnlyList <JSValue>));
 }