public DomEventInstance(DomNodeInstance node, EventInfo eventInfo) { Getter = new ClrFunctionInstance(node.Engine, (thisObject, arguments) => _function ?? JsValue.Null); Setter = new ClrFunctionInstance(node.Engine, (thisObject, arguments) => { if (_handler != null) { eventInfo.RemoveEventHandler(node.Value, _handler); _handler = null; _function = null; } if (arguments[0].Is<FunctionInstance>()) { _function = arguments[0].As<FunctionInstance>(); _handler = (s, ev) => { var sender = s.ToJsValue(node.Context); var args = ev.ToJsValue(node.Context); _function.Call(sender, new [] { args }); }; eventInfo.AddEventHandler(node.Value, _handler); } return arguments[0]; }); }
public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, JsValue[] args, EnvironmentRecord env, bool strict) { var obj = new ArgumentsInstance(engine, self => { var len = args.Length; self.FastAddProperty("length", len, true, false, true); var map = engine.Object.Construct(Arguments.Empty); var mappedNamed = new List<string>(); var indx = 0; while (indx <= len - 1) { var indxStr = TypeConverter.ToString(indx); var val = args[indx]; self.FastAddProperty(indxStr, val, true, true, true); if (indx < names.Length) { var name = names[indx]; if (!strict && !mappedNamed.Contains(name)) { mappedNamed.Add(name); Func<JsValue, JsValue> g = n => env.GetBindingValue(name, false); var p = new Action<JsValue, JsValue>((n, o) => env.SetMutableBinding(name, o, true)); map.DefineOwnProperty(indxStr, new ClrAccessDescriptor(engine, g, p) { Configurable = true }, false); } } indx++; } // step 12 if (mappedNamed.Count > 0) { self.ParameterMap = map; } // step 13 if (!strict) { self.FastAddProperty("callee", func, true, false, true); } // step 14 else { var thrower = engine.Function.ThrowTypeError; self.DefineOwnProperty("caller", new PropertyDescriptor(get: thrower, set: thrower, enumerable: false, configurable: false), false); self.DefineOwnProperty("callee", new PropertyDescriptor(get: thrower, set: thrower, enumerable: false, configurable: false), false); } }); // These properties are pre-initialized as their don't trigger // the EnsureInitialized() event and are cheap obj.Prototype = engine.Object.PrototypeObject; obj.Extensible = true; obj.Strict = strict; return obj; }
// http://www.ecma-international.org/ecma-262/5.1/#sec-10.5 public void DeclarationBindingInstantiation(DeclarationBindingType declarationBindingType, IList<FunctionDeclaration> functionDeclarations, IList<VariableDeclaration> variableDeclarations, FunctionInstance functionInstance, JsValue[] arguments) { var env = ExecutionContext.VariableEnvironment.Record; bool configurableBindings = declarationBindingType == DeclarationBindingType.EvalCode; var strict = StrictModeScope.IsStrictModeCode; if (declarationBindingType == DeclarationBindingType.FunctionCode) { var argCount = arguments.Length; var n = 0; foreach (var argName in functionInstance.FormalParameters) { n++; var v = n > argCount ? Undefined.Instance : arguments[n - 1]; var argAlreadyDeclared = env.HasBinding(argName); if (!argAlreadyDeclared) { env.CreateMutableBinding(argName); } env.SetMutableBinding(argName, v, strict); } } foreach (var f in functionDeclarations) { var fn = f.Id.Name; var fo = Function.CreateFunctionObject(f); var funcAlreadyDeclared = env.HasBinding(fn); if (!funcAlreadyDeclared) { env.CreateMutableBinding(fn, configurableBindings); } else { if (env == GlobalEnvironment.Record) { var go = Global; var existingProp = go.GetProperty(fn); if (existingProp.Configurable.Value.AsBoolean()) { go.DefineOwnProperty(fn, new PropertyDescriptor( value: Undefined.Instance, writable: true, enumerable: true, configurable: configurableBindings ), true); } else { if (existingProp.IsAccessorDescriptor() || (!existingProp.Enumerable.Value.AsBoolean())) { throw new JavaScriptException(TypeError); } } } } env.SetMutableBinding(fn, fo, strict); } var argumentsAlreadyDeclared = env.HasBinding("arguments"); if (declarationBindingType == DeclarationBindingType.FunctionCode && !argumentsAlreadyDeclared) { var argsObj = ArgumentsInstance.CreateArgumentsObject(this, functionInstance, functionInstance.FormalParameters, arguments, env, strict); if (strict) { var declEnv = env as DeclarativeEnvironmentRecord; if (declEnv == null) { throw new ArgumentException(); } declEnv.CreateImmutableBinding("arguments"); declEnv.InitializeImmutableBinding("arguments", argsObj); } else { env.CreateMutableBinding("arguments"); env.SetMutableBinding("arguments", argsObj, false); } } // process all variable declarations in the current parser scope foreach (var d in variableDeclarations.SelectMany(x => x.Declarations)) { var dn = d.Id.Name; var varAlreadyDeclared = env.HasBinding(dn); if (!varAlreadyDeclared) { env.CreateMutableBinding(dn, configurableBindings); env.SetMutableBinding(dn, Undefined.Instance, strict); } } }