public override void Put(string propertyName, JsValue value, bool throwOnError) { if (!CanPut(propertyName)) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } } else { var ownProperty = GetOwnProperty(propertyName); if (ownProperty.IsDataDescriptor()) { ownProperty.Value = value; } else { PropertyDescriptor property = GetProperty(propertyName); if (property.IsAccessorDescriptor()) { property.Set.TryCast <ICallable>().Call(new JsValue(this), new JsValue[1] { value }); } else if (_indexPropertyStr != null) { var val = _converter.ConvertToObject(value, _indexPropertyStr.PropertyType); _indexPropertyStr.SetValue(Target, val, new object[] { propertyName }); } else if (_indexPropertyUlong != null && ulong.TryParse(propertyName, out var uLongIndex)) { var val = _converter.ConvertToObject(value, _indexPropertyUlong.PropertyType); _indexPropertyUlong.SetValue(Target, val, new object[] { uLongIndex }); } else if (_indexPropertyInt != null && int.TryParse(propertyName, out var intIndex)) { var val = _converter.ConvertToObject(value, _indexPropertyInt.PropertyType); _indexPropertyInt.SetValue(Target, val, new object[] { intIndex }); } else if (_indexPropertyObject != null) { var val = _converter.ConvertToObject(value, _indexPropertyObject.PropertyType); _indexPropertyObject.SetValue(Target, val, new object[] { propertyName }); } else { var desc = new PropertyDescriptor(value, true, true, true); DefineOwnProperty(propertyName, desc, throwOnError); } } } }
private bool CanSetLength() { if (!_length.IsAccessorDescriptor()) { return(_length.Writable); } var set = _length.Set; return(set is not null && !set.IsUndefined()); }
public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc) { if (_hasRestParameter) { // immutable return(true); } EnsureInitialized(); if (!(_func is null) && !ReferenceEquals(ParameterMap, null)) { var map = ParameterMap; var isMapped = map.GetOwnProperty(property); var allowed = base.DefineOwnProperty(property, desc); if (!allowed) { return(false); } if (isMapped != PropertyDescriptor.Undefined) { if (desc.IsAccessorDescriptor()) { map.Delete(property); } else { var descValue = desc.Value; if (!ReferenceEquals(descValue, null) && !descValue.IsUndefined()) { map.Set(property, descValue, false); } if (desc.WritableSet && !desc.Writable) { map.Delete(property); } } } return(true); } return(base.DefineOwnProperty(property, desc)); }
public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError) { EnsureInitialized(); if (!_strict && !ReferenceEquals(ParameterMap, null)) { var map = ParameterMap; var isMapped = map.GetOwnProperty(propertyName); var allowed = base.DefineOwnProperty(propertyName, desc, false); if (!allowed) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } } if (isMapped != PropertyDescriptor.Undefined) { if (desc.IsAccessorDescriptor()) { map.Delete(propertyName, false); } else { var descValue = desc.Value; if (!ReferenceEquals(descValue, null) && !descValue.IsUndefined()) { map.Put(propertyName, descValue, throwOnError); } if (desc.WritableSet && !desc.Writable) { map.Delete(propertyName, false); } } } return(true); } return(base.DefineOwnProperty(propertyName, desc, throwOnError)); }
public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError) { EnsureInitialized(); if (!Strict && ParameterMap != null) { var map = ParameterMap; var isMapped = map.GetOwnProperty(propertyName); var allowed = base.DefineOwnProperty(propertyName, desc, false); if (!allowed) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } } if (isMapped != PropertyDescriptor.Undefined) { if (desc.IsAccessorDescriptor()) { map.Delete(propertyName, false); } else { if (desc.Value != null && desc.Value != Undefined.Instance) { map.Put(propertyName, desc.Value, throwOnError); } if (desc.Writable.HasValue && desc.Writable.Value == false) { map.Delete(propertyName, false); } } } return(true); } return(base.DefineOwnProperty(propertyName, desc, throwOnError)); }
public JsValue EvaluateObjectExpression(ObjectExpression objectExpression) { // http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5 var obj = _engine.Object.Construct(Arguments.Empty); foreach (var property in objectExpression.Properties) { var propName = property.Key.GetKey(); var previous = obj.GetOwnProperty(propName); PropertyDescriptor propDesc; switch (property.Kind) { case PropertyKind.Data: var exprValue = _engine.EvaluateExpression(property.Value); var propValue = _engine.GetValue(exprValue); propDesc = new PropertyDescriptor(propValue, true, true, true); break; case PropertyKind.Get: var getter = property.Value as FunctionExpression; if (getter == null) { throw new JavaScriptException(_engine.SyntaxError); } ScriptFunctionInstance get; using (new StrictModeScope(getter.Strict)) { get = new ScriptFunctionInstance( _engine, getter, _engine.ExecutionContext.LexicalEnvironment, StrictModeScope.IsStrictModeCode ); } propDesc = new PropertyDescriptor(get: get, set: null, enumerable: true, configurable: true); break; case PropertyKind.Set: var setter = property.Value as FunctionExpression; if (setter == null) { throw new JavaScriptException(_engine.SyntaxError); } ScriptFunctionInstance set; using (new StrictModeScope(setter.Strict)) { set = new ScriptFunctionInstance( _engine, setter, _engine.ExecutionContext.LexicalEnvironment, StrictModeScope.IsStrictModeCode ); } propDesc = new PropertyDescriptor(get: null, set: set, enumerable: true, configurable: true); break; default: throw new ArgumentOutOfRangeException(); } if (previous != PropertyDescriptor.Undefined) { if (StrictModeScope.IsStrictModeCode && previous.IsDataDescriptor() && propDesc.IsDataDescriptor()) { throw new JavaScriptException(_engine.SyntaxError); } if (previous.IsDataDescriptor() && propDesc.IsAccessorDescriptor()) { throw new JavaScriptException(_engine.SyntaxError); } if (previous.IsAccessorDescriptor() && propDesc.IsDataDescriptor()) { throw new JavaScriptException(_engine.SyntaxError); } if (previous.IsAccessorDescriptor() && propDesc.IsAccessorDescriptor()) { if (propDesc.Set != null && previous.Set != null) { throw new JavaScriptException(_engine.SyntaxError); } if (propDesc.Get != null && previous.Get != null) { throw new JavaScriptException(_engine.SyntaxError); } } } obj.DefineOwnProperty(propName, propDesc, false); } return(obj); }
/// <summary> /// Creates or alters the named own property to /// have the state described by a Property /// Descriptor. The flag controls failure handling. /// </summary> /// <param name="propertyName"></param> /// <param name="desc"></param> /// <param name="throwOnError"></param> /// <returns></returns> public virtual bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError) { var current = GetOwnProperty(propertyName); if (current == desc) { return(true); } if (current == PropertyDescriptor.Undefined) { if (!Extensible) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } else { if (desc.IsGenericDescriptor() || desc.IsDataDescriptor()) { SetOwnProperty(propertyName, new PropertyDescriptor(desc) { Value = desc.Value != null ? desc.Value : JsValue.Undefined, Writable = desc.Writable.HasValue ? desc.Writable.Value : false, Enumerable = desc.Enumerable.HasValue ? desc.Enumerable.Value : false, Configurable = desc.Configurable.HasValue ? desc.Configurable.Value : false }); } else { SetOwnProperty(propertyName, new PropertyDescriptor(desc) { Get = desc.Get, Set = desc.Set, Enumerable = desc.Enumerable.HasValue ? desc.Enumerable : false, Configurable = desc.Configurable.HasValue ? desc.Configurable : false, }); } } return(true); } // Step 5 if (!current.Configurable.HasValue && !current.Enumerable.HasValue && !current.Writable.HasValue && current.Get == null && current.Set == null && current.Value == null) { return(true); } // Step 6 if ( current.Configurable == desc.Configurable && current.Writable == desc.Writable && current.Enumerable == desc.Enumerable && ((current.Get == null && desc.Get == null) || (current.Get != null && desc.Get != null && ExpressionInterpreter.SameValue(current.Get, desc.Get))) && ((current.Set == null && desc.Set == null) || (current.Set != null && desc.Set != null && ExpressionInterpreter.SameValue(current.Set, desc.Set))) && ((current.Value == null && desc.Value == null) || (current.Value != null && desc.Value != null && ExpressionInterpreter.StrictlyEqual(current.Value, desc.Value))) ) { return(true); } if (!current.Configurable.HasValue || !current.Configurable.Value) { if (desc.Configurable.HasValue && desc.Configurable.Value) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } if (desc.Enumerable.HasValue && (!current.Enumerable.HasValue || desc.Enumerable.Value != current.Enumerable.Value)) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } } if (!desc.IsGenericDescriptor()) { if (current.IsDataDescriptor() != desc.IsDataDescriptor()) { if (!current.Configurable.HasValue || !current.Configurable.Value) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } if (current.IsDataDescriptor()) { SetOwnProperty(propertyName, current = new PropertyDescriptor( get: Undefined.Instance, set: Undefined.Instance, enumerable: current.Enumerable, configurable: current.Configurable )); } else { SetOwnProperty(propertyName, current = new PropertyDescriptor( value: Undefined.Instance, writable: null, enumerable: current.Enumerable, configurable: current.Configurable )); } } else if (current.IsDataDescriptor() && desc.IsDataDescriptor()) { if (!current.Configurable.HasValue || current.Configurable.Value == false) { if (!current.Writable.HasValue || !current.Writable.Value && desc.Writable.HasValue && desc.Writable.Value) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } if (!current.Writable.Value) { if (desc.Value != null && !ExpressionInterpreter.SameValue(desc.Value, current.Value)) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } } } } else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor()) { if (!current.Configurable.HasValue || !current.Configurable.Value) { if ((desc.Set != null && !ExpressionInterpreter.SameValue(desc.Set, current.Set != null ? current.Set : Undefined.Instance)) || (desc.Get != null && !ExpressionInterpreter.SameValue(desc.Get, current.Get != null ? current.Get : Undefined.Instance))) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } } } } if (desc.Value != null) { current.Value = desc.Value; } if (desc.Writable.HasValue) { current.Writable = desc.Writable; } if (desc.Enumerable.HasValue) { current.Enumerable = desc.Enumerable; } if (desc.Configurable.HasValue) { current.Configurable = desc.Configurable; } if (desc.Get != null) { current.Get = desc.Get; } if (desc.Set != null) { current.Set = desc.Set; } return(true); }
/// <summary> /// Creates or alters the named own property to /// have the state described by a Property /// Descriptor. The flag controls failure handling. /// </summary> /// <param name="propertyName"></param> /// <param name="desc"></param> /// <param name="throwOnError"></param> /// <returns></returns> public virtual bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError) { var current = GetOwnProperty(propertyName); if (current == PropertyDescriptor.Undefined) { if (!Extensible) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } else { if (desc.IsGenericDescriptor() || desc.IsDataDescriptor()) { Properties[propertyName] = new PropertyDescriptor(desc) { Value = desc.Value.HasValue ? desc.Value : JsValue.Undefined, Writable = desc.Writable.HasValue ? desc.Writable : false }; } else { Properties[propertyName] = new PropertyDescriptor(desc) { Enumerable = desc.Enumerable.HasValue ? desc.Enumerable : false, Configurable = desc.Configurable.HasValue ? desc.Configurable : false, }; } } return(true); } // Step 5 if (!current.Configurable.HasValue && !current.Enumerable.HasValue && !current.Writable.HasValue && !current.Get.HasValue && !current.Set.HasValue && !current.Value.HasValue) { return(true); } // Step 6 var configurableIsSame = current.Configurable.HasValue ? desc.Configurable.HasValue && (current.Configurable.Value == desc.Configurable.Value) : !desc.Configurable.HasValue; var enumerableIsSame = current.Enumerable.HasValue ? desc.Enumerable.HasValue && (current.Enumerable.Value == desc.Enumerable.Value) : !desc.Enumerable.HasValue; var writableIsSame = true; var valueIsSame = true; if (current.IsDataDescriptor() && desc.IsDataDescriptor()) { var currentDataDescriptor = current; var descDataDescriptor = desc; writableIsSame = currentDataDescriptor.Writable.HasValue ? descDataDescriptor.Writable.HasValue && (currentDataDescriptor.Writable.Value == descDataDescriptor.Writable.Value) : !descDataDescriptor.Writable.HasValue; var valueA = currentDataDescriptor.Value.HasValue ? currentDataDescriptor.Value.Value : Undefined.Instance; var valueB = descDataDescriptor.Value.HasValue ? descDataDescriptor.Value.Value : Undefined.Instance; valueIsSame = ExpressionInterpreter.SameValue(valueA, valueB); } else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor()) { var currentAccessorDescriptor = current; var descAccessorDescriptor = desc; var getValueA = currentAccessorDescriptor.Get.HasValue ? currentAccessorDescriptor.Get.Value : Undefined.Instance; var getValueB = descAccessorDescriptor.Get.HasValue ? descAccessorDescriptor.Get.Value : Undefined.Instance; var setValueA = currentAccessorDescriptor.Set.HasValue ? currentAccessorDescriptor.Set.Value : Undefined.Instance; var setValueB = descAccessorDescriptor.Set.HasValue ? descAccessorDescriptor.Set.Value : Undefined.Instance; valueIsSame = ExpressionInterpreter.SameValue(getValueA, getValueB) && ExpressionInterpreter.SameValue(setValueA, setValueB); } else { valueIsSame = false; } if (configurableIsSame && enumerableIsSame && writableIsSame && valueIsSame) { return(true); } if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean()) { if (desc.Configurable.HasValue && desc.Configurable.Value.AsBoolean()) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } if (desc.Enumerable.HasValue && (!current.Enumerable.HasValue || desc.Enumerable.Value != current.Enumerable.Value)) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } } if (!desc.IsGenericDescriptor()) { if (current.IsDataDescriptor() != desc.IsDataDescriptor()) { if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean()) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } if (current.IsDataDescriptor()) { Properties[propertyName] = current = new PropertyDescriptor( get: Undefined.Instance, set: Undefined.Instance, enumerable: current.Enumerable.HasValue && current.Enumerable.Value.AsBoolean(), configurable: current.Configurable.HasValue && current.Configurable.Value.AsBoolean() ); } else { Properties[propertyName] = current = new PropertyDescriptor( value: Undefined.Instance, writable: null, enumerable: current.Enumerable.HasValue && current.Enumerable.Value.AsBoolean(), configurable: current.Configurable.HasValue && current.Configurable.Value.AsBoolean() ); } } else if (current.IsDataDescriptor() && desc.IsDataDescriptor()) { if (!current.Configurable.HasValue || current.Configurable.Value.AsBoolean() == false) { if (!current.Writable.HasValue || !current.Writable.Value.AsBoolean() && desc.Writable.HasValue && desc.Writable.Value.AsBoolean()) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } if (!current.Writable.Value.AsBoolean()) { if (desc.Value.HasValue && !valueIsSame) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } } } } else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor()) { if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean()) { if ((desc.Set.HasValue && !ExpressionInterpreter.SameValue(desc.Set.Value, current.Set.HasValue ? current.Set.Value : Undefined.Instance)) || (desc.Get.HasValue && !ExpressionInterpreter.SameValue(desc.Get.Value, current.Get.HasValue ? current.Get.Value : Undefined.Instance))) { if (throwOnError) { throw new JavaScriptException(Engine.TypeError); } return(false); } } } } if (desc.Value.HasValue) { current.Value = desc.Value; } if (desc.Writable.HasValue) { current.Writable = desc.Writable; } if (desc.Enumerable.HasValue) { current.Enumerable = desc.Enumerable; } if (desc.Configurable.HasValue) { current.Configurable = desc.Configurable; } if (desc.Get.HasValue) { current.Get = desc.Get; } if (desc.Set.HasValue) { current.Set = desc.Set; } return(true); }
/// <summary> /// Creates or alters the named own property to /// have the state described by a Property /// Descriptor. The flag controls failure handling. /// </summary> /// <param name="propertyName"></param> /// <param name="desc"></param> /// <param name="throwOnError"></param> /// <returns></returns> public virtual bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError) { var current = GetOwnProperty(propertyName); if (current == desc) { return(true); } var descValue = desc.Value; if (current == PropertyDescriptor.Undefined) { if (!Extensible) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } else { if (desc.IsGenericDescriptor() || desc.IsDataDescriptor()) { PropertyDescriptor propertyDescriptor; if ((desc._flags & PropertyFlag.ConfigurableEnumerableWritable) == PropertyFlag.ConfigurableEnumerableWritable) { propertyDescriptor = new PropertyDescriptor(descValue ?? Undefined, PropertyFlag.ConfigurableEnumerableWritable); } else if ((desc._flags & PropertyFlag.ConfigurableEnumerableWritable) == 0) { propertyDescriptor = new PropertyDescriptor(descValue ?? Undefined, PropertyFlag.AllForbidden); } else { propertyDescriptor = new PropertyDescriptor(desc) { Value = descValue ?? Undefined }; } SetOwnProperty(propertyName, propertyDescriptor); } else { SetOwnProperty(propertyName, new GetSetPropertyDescriptor(desc)); } } return(true); } // Step 5 var currentGet = current.Get; var currentSet = current.Set; var currentValue = current.Value; if ((current._flags & PropertyFlag.ConfigurableSet | PropertyFlag.EnumerableSet | PropertyFlag.WritableSet) == 0 && ReferenceEquals(currentGet, null) && ReferenceEquals(currentSet, null) && ReferenceEquals(currentValue, null)) { return(true); } // Step 6 var descGet = desc.Get; var descSet = desc.Set; if ( current.Configurable == desc.Configurable && current.ConfigurableSet == desc.ConfigurableSet && current.Writable == desc.Writable && current.WritableSet == desc.WritableSet && current.Enumerable == desc.Enumerable && current.EnumerableSet == desc.EnumerableSet && ((ReferenceEquals(currentGet, null) && ReferenceEquals(descGet, null)) || (!ReferenceEquals(currentGet, null) && !ReferenceEquals(descGet, null) && ExpressionInterpreter.SameValue(currentGet, descGet))) && ((ReferenceEquals(currentSet, null) && ReferenceEquals(descSet, null)) || (!ReferenceEquals(currentSet, null) && !ReferenceEquals(descSet, null) && ExpressionInterpreter.SameValue(currentSet, descSet))) && ((ReferenceEquals(currentValue, null) && ReferenceEquals(descValue, null)) || (!ReferenceEquals(currentValue, null) && !ReferenceEquals(descValue, null) && ExpressionInterpreter.StrictlyEqual(currentValue, descValue))) ) { return(true); } if (!current.Configurable) { if (desc.Configurable) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } if (desc.EnumerableSet && (desc.Enumerable != current.Enumerable)) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } } if (!desc.IsGenericDescriptor()) { if (current.IsDataDescriptor() != desc.IsDataDescriptor()) { if (!current.Configurable) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } if (current.IsDataDescriptor()) { var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet); SetOwnProperty(propertyName, current = new GetSetPropertyDescriptor( get: JsValue.Undefined, set: JsValue.Undefined, flags: flags )); } else { var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet); SetOwnProperty(propertyName, current = new PropertyDescriptor( value: JsValue.Undefined, flags: flags )); } } else if (current.IsDataDescriptor() && desc.IsDataDescriptor()) { if (!current.Configurable) { if (!current.Writable && desc.Writable) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } if (!current.Writable) { if (!ReferenceEquals(descValue, null) && !ExpressionInterpreter.SameValue(descValue, currentValue)) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } } } } else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor()) { if (!current.Configurable) { if ((!ReferenceEquals(descSet, null) && !ExpressionInterpreter.SameValue(descSet, currentSet ?? Undefined)) || (!ReferenceEquals(descGet, null) && !ExpressionInterpreter.SameValue(descGet, currentGet ?? Undefined))) { if (throwOnError) { ExceptionHelper.ThrowTypeError(Engine); } return(false); } } } } if (!ReferenceEquals(descValue, null)) { current.Value = descValue; } if (desc.WritableSet) { current.Writable = desc.Writable; } if (desc.EnumerableSet) { current.Enumerable = desc.Enumerable; } if (desc.ConfigurableSet) { current.Configurable = desc.Configurable; } PropertyDescriptor mutable = null; if (!ReferenceEquals(descGet, null)) { mutable = new GetSetPropertyDescriptor(mutable ?? current); ((GetSetPropertyDescriptor)mutable).SetGet(descGet); } if (!ReferenceEquals(descSet, null)) { mutable = new GetSetPropertyDescriptor(mutable ?? current); ((GetSetPropertyDescriptor)mutable).SetSet(descSet); } if (mutable != null) { // replace old with new type that supports get and set FastSetProperty(propertyName, mutable); } return(true); }