internal ScriptValue OrdinaryToPrimitive([NotNull] ScriptObject obj, ScriptValue.Type preferredType)
        {
            //https://tc39.github.io/ecma262/#sec-ordinarytoprimitive
            var methodNames = new string[2];

            if (preferredType == ScriptValue.Type.String)
            {
                methodNames[0] = "toString";
                methodNames[1] = "valueOf";
            }
            else
            {
                methodNames[0] = "valueOf";
                methodNames[1] = "toString";
            }

            foreach (var methodName in methodNames)
            {
                var method = obj.Get(methodName, obj);

                if (IsCallable(method))
                {
                    var result = Call((ScriptObject)method, obj);
                    if (!result.IsObject)
                    {
                        return(result);
                    }
                }
            }

            throw CreateTypeError();
        }
        internal ScriptValue ToPrimitive(ScriptValue input, ScriptValue.Type preferredType = ScriptValue.Type.Undefined)
        {
            if (input.IsObject)
            {
                var exoticToPrimitive = GetMethod(input, Symbol.ToPrimitive);

                if (exoticToPrimitive != null)
                {
                    string hint;
                    if (preferredType == ScriptValue.Type.Undefined)
                    {
                        hint = "default";
                    }
                    else if (preferredType == ScriptValue.Type.String)
                    {
                        hint = "string";
                    }
                    else
                    {
                        hint = "number";
                    }

                    var result = Call(exoticToPrimitive, input, hint);
                    if (!result.IsObject)
                    {
                        return(result);
                    }

                    throw CreateTypeError();
                }

                if (preferredType != ScriptValue.Type.String)
                {
                    preferredType = ScriptValue.Type.Number;
                }

                return(OrdinaryToPrimitive((ScriptObject)input, preferredType));
            }
            return(input);
        }
        private static ScriptValue GetOwnPropertyKeys([NotNull] Agent agent, ScriptValue value, ScriptValue.Type type)
        {
            //https://tc39.github.io/ecma262/#sec-getownpropertykeys
            var obj      = agent.ToObject(value);
            var keys     = obj.OwnPropertyKeys();
            var nameList = keys.Where(x => x.ValueType == type);

            return(ArrayIntrinsics.CreateArrayFromList(agent, nameList));
        }