/// <summary> /// Determines whether an object has a non-inherited property /// </summary> /// <remarks> /// Requires an active script context. /// </remarks> /// <param name="source">The JavaScript value</param> /// <param name="propertyName">The name of the property</param> /// <returns>Whether the object has the non-inherited property</returns> public static bool HasOwnProperty(this JsValue source, string propertyName) { JsPropertyId propertyId = JsPropertyId.FromString(propertyName); bool result = source.HasOwnProperty(propertyId); return(result); }
private JsValue Bind(JsValue thisObj, JsValue[] arguments) { if (!(thisObj is ICallable)) { ExceptionHelper.ThrowTypeError(Engine, "Bind must be called on a function"); } var thisArg = arguments.At(0); var f = new BindFunctionInstance(Engine) { TargetFunction = thisObj, BoundThis = thisObj is ArrowFunctionInstance ? Undefined : thisArg, BoundArgs = arguments.Skip(1), _prototype = Engine.Function.PrototypeObject, }; JsNumber l; var targetHasLength = thisObj.HasOwnProperty(CommonProperties.Length); if (targetHasLength) { var targetLen = thisObj.Get(CommonProperties.Length); if (!targetLen.IsNumber()) { l = JsNumber.PositiveZero; } else { targetLen = TypeConverter.ToInteger(targetLen); // first argument is target var argumentsLength = System.Math.Max(0, arguments.Length - 1); l = JsNumber.Create((uint)System.Math.Max(((JsNumber)targetLen)._value - argumentsLength, 0)); } } else { l = JsNumber.PositiveZero; } f._length = new PropertyDescriptor(l, PropertyFlag.Configurable); var targetName = thisObj.Get(CommonProperties.Name); if (!targetName.IsString()) { targetName = JsString.Empty; } f.SetFunctionName(targetName, "bound"); return(f); }
/// <summary> /// https://tc39.es/ecma262/#sec-function.prototype.bind /// </summary> private JsValue Bind(JsValue thisObj, JsValue[] arguments) { if (thisObj is not ICallable) { ExceptionHelper.ThrowTypeError(_realm, "Bind must be called on a function"); } var thisArg = arguments.At(0); var f = BoundFunctionCreate((ObjectInstance)thisObj, thisArg, arguments.Skip(1)); JsNumber l; var targetHasLength = thisObj.HasOwnProperty(CommonProperties.Length); if (targetHasLength) { var targetLen = thisObj.Get(CommonProperties.Length); if (targetLen is not JsNumber number) { l = JsNumber.PositiveZero; } else { if (number.IsPositiveInfinity()) { l = number; } else if (number.IsNegativeInfinity()) { l = JsNumber.PositiveZero; } else { var targetLenAsInt = (long)TypeConverter.ToIntegerOrInfinity(targetLen); // first argument is target var argumentsLength = System.Math.Max(0, arguments.Length - 1); l = JsNumber.Create((ulong)System.Math.Max(targetLenAsInt - argumentsLength, 0)); } } }