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); }
private static ObjectInstance GetPrototypeFromConstructor(JsValue constructor, ObjectInstance intrinsicDefaultProto) { var proto = constructor.Get(CommonProperties.Prototype, constructor) as ObjectInstance; // If Type(proto) is not Object, then // Let realm be ? GetFunctionRealm(constructor). // Set proto to realm's intrinsic object named intrinsicDefaultProto. return(proto ?? intrinsicDefaultProto); }
public static void Call(this JsValue controller, GameEngine engine, string function, params object[] args) { if (engine.GetValue(controller, function).IsUndefined()) { return; } engine.Invoke(controller.Get(function), controller, args); }
internal ObjectInstance GetPrototypeFromConstructor(JsValue constructor, Func <Intrinsics, ObjectInstance> intrinsicDefaultProto) { var proto = constructor.Get(CommonProperties.Prototype, constructor) as ObjectInstance; if (proto is null) { var realm = GetFunctionRealm(constructor); proto = intrinsicDefaultProto(realm.Intrinsics); } return(proto); }
private static JsValue InternalizeJSONProperty(JsValue holder, JsValue name, ICallable reviver) { JsValue temp = holder.Get(name, holder); if (temp is ObjectInstance val) { if (val.IsArray()) { var i = 0UL; var len = TypeConverter.ToLength(val.Get(CommonProperties.Length)); while (i < len) { var prop = JsString.Create(i); var newElement = InternalizeJSONProperty(val, prop, reviver); if (newElement.IsUndefined()) { val.Delete(prop); } else { val.CreateDataProperty(prop, newElement); } i = i + 1; } } else { var keys = val.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Key); foreach (var p in keys) { var newElement = InternalizeJSONProperty(val, p, reviver); if (newElement.IsUndefined()) { val.Delete(p); } else { val.CreateDataProperty(p, newElement); } } } } return(reviver.Call(holder, new[] { name, temp })); }
/// <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)); } } }
static string AddFlagIfPresent(JsValue o, JsValue p, char flag, string s) { return(TypeConverter.ToBoolean(o.Get(p)) ? s + flag : s); }