using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;
namespace Jint.Native.Symbol
{
///
/// http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4
///
public sealed class SymbolPrototype : ObjectInstance
{
private SymbolPrototype(Engine engine)
: base(engine)
{
}
public static SymbolPrototype CreatePrototypeObject(Engine engine, SymbolConstructor symbolConstructor)
{
var obj = new SymbolPrototype(engine);
obj.Prototype = engine.Object.PrototypeObject;
obj.Extensible = true;
obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden));
obj.FastAddProperty("constructor", symbolConstructor, true, false, true);
return obj;
}
public void Configure()
{
FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToSymbolString), true, false, true);
FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOf", ValueOf), true, false, true);
FastAddProperty("toStringTag", new JsString("Symbol"), false, false, true);
FastAddProperty(GlobalSymbolRegistry.ToPrimitive._value, new ClrFunctionInstance(Engine, "toPrimitive", ToPrimitive), false, false, true);
FastAddProperty(GlobalSymbolRegistry.ToStringTag._value, new JsString("Symbol"), false, false, true);
}
public string SymbolDescriptiveString(JsSymbol sym)
{
return $"Symbol({sym.AsSymbol()})";
}
private JsValue ToSymbolString(JsValue thisObject, JsValue[] arguments)
{
if (!thisObject.IsSymbol())
{
ExceptionHelper.ThrowTypeError(Engine);
}
return SymbolDescriptiveString((JsSymbol)thisObject);
}
private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
{
var sym = thisObject.TryCast();
if (ReferenceEquals(sym, null))
{
ExceptionHelper.ThrowTypeError(Engine);
}
return sym.SymbolData;
}
private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
{
if (thisObject.IsSymbol())
{
return thisObject;
}
// Steps 3. and 4.
var o = thisObject.AsInstance();
if (ReferenceEquals(o, null))
{
ExceptionHelper.ThrowTypeError(Engine);
}
return o.SymbolData;
}
}
}