public bool SetPropertyValueIfExists(object key, object value, bool throwOnError)
{
// Do not store nulls - null represents a non-existant value.
value = value ?? Undefined.Value;
// Retrieve information about the property.
var property = this.schema.GetPropertyIndexAndAttributes(key);
if (property.Exists == true)
{
// Check if the property is read-only.
if (property.IsWritable == false)
{
// The property is read-only.
if (throwOnError == true)
throw new JavaScriptException(this.Engine, ErrorType.TypeError, string.Format("The property '{0}' is read-only.", key));
return true;
}
if ((property.Attributes & (PropertyAttributes.IsAccessorProperty | PropertyAttributes.IsLengthProperty)) == 0)
{
// The property contains a simple value. Set the property value.
this.propertyValues[property.Index] = value;
}
else if (property.IsAccessor == true)
{
// The property contains an accessor function. Set the property value by calling the accessor.
((PropertyAccessorValue)this.propertyValues[property.Index]).SetValue(this, value);
}
else
{
// Otherwise, the property is the "magic" length property.
double length = TypeConverter.ToNumber(value);
uint lengthUint32 = TypeConverter.ToUint32(length);
if (length != (double)lengthUint32)
throw new JavaScriptException(this.Engine, ErrorType.RangeError, "Invalid array length");
((ArrayInstance)this).Length = lengthUint32;
}
return true;
}
// Search the prototype chain for a accessor function. If one is found, it will
// prevent the creation of a new property.
bool propertyExistsInPrototype = false;
ObjectInstance prototypeObject = this.prototype;
while (prototypeObject != null)
{
property = prototypeObject.schema.GetPropertyIndexAndAttributes(key);
if (property.Exists == true)
{
if (property.IsAccessor == true)
{
// The property contains an accessor function. Set the property value by calling the accessor.
((PropertyAccessorValue)prototypeObject.propertyValues[property.Index]).SetValue(this, value);
return true;
}
propertyExistsInPrototype = true;
break;
}
prototypeObject = prototypeObject.prototype;
}
// If the property exists in the prototype, create a new property.
if (propertyExistsInPrototype == true)
{
AddProperty(key, value, PropertyAttributes.FullAccess, throwOnError);
return true;
}
// The property does not exist.
return false;
}