using Jint.Native.Object; using Jint.Runtime; using Jint.Runtime.Environments; namespace Jint.Native.Function { public abstract class FunctionInstance : ObjectInstance, ICallable { private readonly Engine _engine; protected FunctionInstance(Engine engine, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine) { _engine = engine; FormalParameters = parameters; Scope = scope; Strict = strict; } /// /// Executed when a function object is used as a function /// /// /// /// public abstract object Call(object thisObject, object[] arguments); public LexicalEnvironment Scope { get; private set; } public string[] FormalParameters { get; private set; } public bool Strict { get; private set; } // todo: implement public object TargetFunction { get; set; } // todo: implement public object BoundThis { get; set; } // todo: implement public object BoundArgs { get; set; } /// /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3 /// /// /// public bool HasInstance(object v) { var vObj = v as ObjectInstance; if (vObj == null) { return false; } var o = Get("prototype") as ObjectInstance; if (o == null) { throw new JavaScriptException(_engine.TypeError); } while (true) { v = vObj.Prototype; if (v == null) { return false; } if (v == o) { return true; } } } public override string Class { get { return "Function"; } } /// /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.4 /// /// /// public override object Get(string propertyName) { var v = base.Get(propertyName); var f = v as FunctionInstance; if (propertyName == "caller" && f != null && f.Strict) { throw new JavaScriptException(_engine.TypeError); } return v; } } }