/// <summary> /// Converts any JavaScript value to a primitive value. /// </summary> /// <param name="value"> The value to convert. </param> /// <param name="preferredType"> Specifies whether toString() or valueOf() should be /// preferred when converting to a primitive. </param> /// <returns> A primitive (non-object) value. </returns> public static object ToPrimitive(object value, PrimitiveTypeHint preferredType) { if (value is ObjectInstance) { return(((ObjectInstance)value).GetPrimitiveValue(preferredType)); } return(value); }
/// <summary> /// Pops the value on the stack, converts it to a primitive value, then pushes the result /// onto the stack. /// </summary> /// <param name="generator"> The IL generator. </param> /// <param name="fromType"> The type to convert from. </param> /// <param name="preferredType"> Specifies whether toString() or valueOf() should be /// preferred when converting to a primitive. </param> public static void ToPrimitive(ILGenerator generator, Type fromType, PrimitiveTypeHint preferredType) { if (fromType == typeof(Nitrassic.Undefined) || fromType == typeof(Nitrassic.Null) || fromType == typeof(bool) || fromType == typeof(string) || fromType == typeof(ConcatenatedString) || fromType == typeof(int) || fromType == typeof(uint) || fromType == typeof(double)) { return; } else if (fromType == typeof(object) || fromType == typeof(Library.ObjectInstance)) { // Otherwise, fall back to calling TypeConverter.ToPrimitive() if (PrimitiveTypeUtilities.IsValueType(fromType)) { generator.Box(fromType); } generator.LoadInt32((int)preferredType); generator.Call(ReflectionHelpers.TypeConverter_ToPrimitive); } else { throw new NotImplementedException("Unsupported primitive type: " + fromType); } }
// JAVASCRIPT INTERNAL FUNCTIONS //_________________________________________________________________________________________ /// <summary> /// Returns a primitive value that represents the current object. Used by the addition and /// equality operators. /// </summary> /// <param name="hint"> Indicates the preferred type of the result. </param> /// <returns> A primitive value that represents the current object. </returns> protected internal override object GetPrimitiveValue(PrimitiveTypeHint typeHint) { if (typeHint == PrimitiveTypeHint.None) return base.GetPrimitiveValue(PrimitiveTypeHint.String); return base.GetPrimitiveValue(typeHint); }
/// <summary> /// Pops the value on the stack, converts it to a primitive value, then pushes the result /// onto the stack. /// </summary> /// <param name="generator"> The IL generator. </param> /// <param name="fromType"> The type to convert from. </param> /// <param name="preferredType"> Specifies whether toString() or valueOf() should be /// preferred when converting to a primitive. </param> public static void ToPrimitive(ILGenerator generator, PrimitiveType fromType, PrimitiveTypeHint preferredType) { switch (fromType) { case PrimitiveType.Undefined: case PrimitiveType.Null: case PrimitiveType.Bool: case PrimitiveType.String: case PrimitiveType.ConcatenatedString: case PrimitiveType.Int32: case PrimitiveType.UInt32: case PrimitiveType.Number: // These are primitives already. break; case PrimitiveType.Any: case PrimitiveType.Object: // Otherwise, fall back to calling TypeConverter.ToPrimitive() generator.LoadEnumValue(preferredType); generator.Call(ReflectionHelpers.TypeConverter_ToPrimitive); break; default: throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType)); } }
// OTHERS //_________________________________________________________________________________________ /// <summary> /// Returns a primitive value that represents the current object. Used by the addition and /// equality operators. /// </summary> /// <param name="hint"> Indicates the preferred type of the result. </param> /// <returns> A primitive value that represents the current object. </returns> protected internal virtual object GetPrimitiveValue(PrimitiveTypeHint typeHint) { if (typeHint == PrimitiveTypeHint.None || typeHint == PrimitiveTypeHint.Number) { // Try calling valueOf(). object valueOfResult; if (TryCallMemberFunction(out valueOfResult, "valueOf") == true) { // Return value must be primitive. if (valueOfResult is double || TypeUtilities.IsPrimitive(valueOfResult) == true) return valueOfResult; } // Try calling toString(). object toStringResult; if (TryCallMemberFunction(out toStringResult, "toString") == true) { // Return value must be primitive. if (toStringResult is string || TypeUtilities.IsPrimitive(toStringResult) == true) return toStringResult; } } else { // Try calling toString(). object toStringResult; if (TryCallMemberFunction(out toStringResult, "toString") == true) { // Return value must be primitive. if (toStringResult is string || TypeUtilities.IsPrimitive(toStringResult) == true) return toStringResult; } // Try calling valueOf(). object valueOfResult; if (TryCallMemberFunction(out valueOfResult, "valueOf") == true) { // Return value must be primitive. if (valueOfResult is double || TypeUtilities.IsPrimitive(valueOfResult) == true) return valueOfResult; } } throw new JavaScriptException(this.Engine, "TypeError", "Attempted conversion of the object to a primitive value failed. Check the toString() and valueOf() functions."); }
/// <summary> /// Pops the value on the stack, converts it to a primitive value, then pushes the result /// onto the stack. /// </summary> /// <param name="generator"> The IL generator. </param> /// <param name="fromType"> The type to convert from. </param> /// <param name="preferredType"> Specifies whether toString() or valueOf() should be /// preferred when converting to a primitive. </param> public static void ToPrimitive(ILGenerator generator, PrimitiveType fromType, PrimitiveTypeHint preferredType) { switch (fromType) { case PrimitiveType.Undefined: case PrimitiveType.Null: case PrimitiveType.Bool: case PrimitiveType.String: case PrimitiveType.ConcatenatedString: case PrimitiveType.Int32: case PrimitiveType.UInt32: case PrimitiveType.Number: // These are primitives already. break; case PrimitiveType.Any: case PrimitiveType.Object: // Otherwise, fall back to calling TypeConverter.ToPrimitive() generator.LoadInt32((int)preferredType); generator.Call(ReflectionHelpers.TypeConverter_ToPrimitive); break; default: throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType)); } }
// OTHERS //_________________________________________________________________________________________ /// <summary> /// Returns a primitive value that represents the current object. Used by the addition and /// equality operators. /// </summary> /// <param name="typeHint"> Indicates the preferred type of the result. </param> /// <returns> A primitive value that represents the current object. </returns> internal object GetPrimitiveValue(PrimitiveTypeHint typeHint) { // The first step is to try calling the @@toPrimitive symbol. string hintStr; switch (typeHint) { case PrimitiveTypeHint.None: hintStr = "default"; break; case PrimitiveTypeHint.Number: hintStr = "number"; break; case PrimitiveTypeHint.String: hintStr = "string"; break; default: throw new InvalidOperationException($"Unsupported PrimitiveTypeHint value '{typeHint}'."); } object toPrimitiveResult; if (TryCallMemberFunction(out toPrimitiveResult, Engine.Symbol.ToPrimitive, hintStr) == true) { // Return value must be primitive. if (TypeUtilities.IsPrimitive(toPrimitiveResult) == false) throw new JavaScriptException(Engine, ErrorType.TypeError, "Cannot convert object to primitive value."); return toPrimitiveResult; } // If that didn't work. return GetPrimitiveValuePreES6(typeHint); }