コード例 #1
0
        /// Implementation from ObjectInstance official specs as the one
        /// in ObjectInstance is optimized for the general case and wouldn't work
        /// for arrays
        public override void Put(string propertyName, JsValue value, bool throwOnError)
        {
            if (!CanPut(propertyName))
            {
                if (throwOnError)
                {
                    ExceptionHelper.ThrowTypeError(Engine);
                }

                return;
            }

            var ownDesc = GetOwnProperty(propertyName);

            if (ownDesc.IsDataDescriptor())
            {
                var valueDesc = new PropertyDescriptor(value, PropertyFlag.None);
                DefineOwnProperty(propertyName, valueDesc, throwOnError);
                return;
            }

            // property is an accessor or inherited
            var desc = GetProperty(propertyName);

            if (desc.IsAccessorDescriptor())
            {
                var setter = desc.Set.TryCast <ICallable>();
                setter.Call(this, new[] { value });
            }
            else
            {
                var newDesc = new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable);
                DefineOwnProperty(propertyName, newDesc, throwOnError);
            }
        }
コード例 #2
0
        public ArrayInstance(Engine engine, Dictionary <uint, PropertyDescriptor> items) : base(engine, objectClass: "Array")
        {
            _sparse = items;
            var length = items?.Count ?? 0;

            _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable);
        }
コード例 #3
0
        internal void WriteArrayValue(uint index, PropertyDescriptor desc)
        {
            // calculate eagerly so we know if we outgrow
            var newSize = _dense != null && index >= (uint)_dense.Length
                ? System.Math.Max(index, System.Math.Max(_dense.Length, 2)) * 2
                : 0;

            bool canUseDense = _dense != null &&
                               index < MaxDenseArrayLength &&
                               newSize < MaxDenseArrayLength &&
                               index < _dense.Length + 50;    // looks sparse

            if (canUseDense)
            {
                var temp = _dense;
                if (index >= (uint)temp.Length)
                {
                    EnsureCapacity((uint)newSize);
                }

                _dense[index] = desc;
            }
            else
            {
                if (_dense != null)
                {
                    ConvertToSparse();
                }
                _sparse[index] = desc;
            }
        }
コード例 #4
0
ファイル: ArrayInstance.cs プロジェクト: Willy-Kimura/jint
        /// Implementation from ObjectInstance official specs as the one 
        /// in ObjectInstance is optimized for the general case and wouldn't work 
        /// for arrays
        public override void Put(string propertyName, JsValue value, bool throwOnError)
        {
            if (!CanPut(propertyName))
            {
                if (throwOnError)
                {
                    throw new JavaScriptException(Engine.TypeError);
                }

                return;
            }

            var ownDesc = GetOwnProperty(propertyName);

            if (ownDesc.IsDataDescriptor())
            {
                var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable: null, configurable: null);
                DefineOwnProperty(propertyName, valueDesc, throwOnError);
                return;
            }

            // property is an accessor or inherited
            var desc = GetProperty(propertyName);

            if (desc.IsAccessorDescriptor())
            {
                var setter = desc.Set.Value.TryCast<ICallable>();
                setter.Call(new JsValue(this), new[] { value });
            }
            else
            {
                var newDesc = new PropertyDescriptor(value, true, true, true);
                DefineOwnProperty(propertyName, newDesc, throwOnError);
            }
        }
コード例 #5
0
        internal ArrayInstance Map(JsValue[] arguments)
        {
            var callbackfn = arguments.At(0);
            var thisArg    = arguments.At(1);

            var len = GetLength();

            var callable = GetCallable(callbackfn);
            var a        = Engine.Array.ConstructFast(len);
            var args     = _engine._jsValueArrayPool.RentArray(3);

            args[2] = this;
            for (uint k = 0; k < len; k++)
            {
                var kvalue = args[0];
                if (TryGetValue(k, out kvalue))
                {
                    args[0] = kvalue;
                    args[1] = k;
                    var mappedValue = callable.Call(thisArg, args);
                    var desc        = new PropertyDescriptor(mappedValue, PropertyFlag.ConfigurableEnumerableWritable);
                    if (a._dense != null && k < (uint)a._dense.Length)
                    {
                        a._dense[k] = desc;
                    }
                    else
                    {
                        a.WriteArrayValue(k, desc);
                    }
                }
            }

            _engine._jsValueArrayPool.ReturnArray(args);
            return(a);
        }
コード例 #6
0
 internal void EnsureCapacity(uint capacity)
 {
     if (capacity > (uint)_dense.Length)
     {
         // need to grow
         var newArray = new PropertyDescriptor[capacity];
         System.Array.Copy(_dense, newArray, _dense.Length);
         _dense = newArray;
     }
 }
コード例 #7
0
        protected override void AddProperty(string propertyName, PropertyDescriptor descriptor)
        {
            if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
            {
                _length = descriptor;
                return;
            }

            base.AddProperty(propertyName, descriptor);
        }
コード例 #8
0
        protected override bool TryGetProperty(string propertyName, out PropertyDescriptor descriptor)
        {
            if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
            {
                descriptor = _length;
                return(_length != null);
            }

            return(base.TryGetProperty(propertyName, out descriptor));
        }
コード例 #9
0
        private bool TryGetDescriptor(uint index, out PropertyDescriptor descriptor)
        {
            if (_dense != null)
            {
                descriptor = null;
                if (index < (uint)_dense.Length)
                {
                    descriptor = _dense[index];
                }

                return(descriptor != null);
            }

            return(_sparse.TryGetValue(index, out descriptor));
        }
コード例 #10
0
        public override void RemoveOwnProperty(string p)
        {
            uint index;

            if (IsArrayIndex(p, out index))
            {
                DeleteAt(index);
            }

            if (p == PropertyNameLength)
            {
                _length = null;
            }

            base.RemoveOwnProperty(p);
        }
コード例 #11
0
        public ArrayInstance(Engine engine, PropertyDescriptor[] items) : base(engine, objectClass: "Array")
        {
            int length = 0;

            if (items == null || items.Length == 0)
            {
                _dense = System.ArrayExt.Empty <PropertyDescriptor>();
                length = 0;
            }
            else
            {
                _dense = items;
                length = items.Length;
            }

            _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable);
        }
コード例 #12
0
        internal uint Push(JsValue[] arguments)
        {
            var initialLength = GetLength();
            var newLength     = initialLength + arguments.Length;

            // if we see that we are bringing more than normal growth algorithm handles, ensure capacity eagerly
            if (_dense != null &&
                initialLength != 0 &&
                arguments.Length > initialLength * 2 &&
                newLength <= MaxDenseArrayLength)
            {
                EnsureCapacity((uint)newLength);
            }

            double n = initialLength;

            for (var i = 0; i < arguments.Length; i++)
            {
                var desc = new PropertyDescriptor(arguments[i], PropertyFlag.ConfigurableEnumerableWritable);
                if (_dense != null && n < _dense.Length)
                {
                    _dense[(int)n] = desc;
                }
                else if (n < uint.MaxValue)
                {
                    WriteArrayValue((uint)n, desc);
                }
                else
                {
                    DefineOwnProperty(TypeConverter.ToString((uint)n), desc, true);
                }
                n++;
            }

            // check if we can set length fast without breaking ECMA specification
            if (n < uint.MaxValue && CanPut(PropertyNameLength))
            {
                _length.Value = (uint)n;
            }
            else
            {
                Put(PropertyNameLength, newLength, true);
            }

            return((uint)n);
        }
コード例 #13
0
        protected internal override void SetOwnProperty(string propertyName, PropertyDescriptor desc)
        {
            uint index;

            if (IsArrayIndex(propertyName, out index))
            {
                WriteArrayValue(index, desc);
            }
            else if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
            {
                _length = desc;
            }
            else
            {
                base.SetOwnProperty(propertyName, desc);
            }
        }
コード例 #14
0
ファイル: ArgumentsInstance.cs プロジェクト: honestegg/jint
        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.HasValue && desc.Value.Value != Undefined.Instance)
                        {
                            map.Put(propertyName, desc.Value.Value, throwOnError);
                        }

                        if (desc.Writable.HasValue && desc.Writable.Value == false)
                        {
                            map.Delete(propertyName, false);
                        }
                    }
                }

                return true;
            }

            return base.DefineOwnProperty(propertyName, desc, throwOnError);
        }
コード例 #15
0
ファイル: ObjectInstance.cs プロジェクト: nilproject/jint
 protected virtual void SetOwnProperty(string propertyName, PropertyDescriptor desc)
 {
     Properties[propertyName] = desc;
 }
コード例 #16
0
ファイル: ObjectInstance.cs プロジェクト: Rohansi/jint
        /// <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;
        }
コード例 #17
0
ファイル: ObjectInstance.cs プロジェクト: Rohansi/jint
 /// <summary>
 /// Optimized version of [[Put]] when the property is known to be already declared 
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 public void FastSetProperty(string name, PropertyDescriptor value)
 {
     Properties[name] = value;
 }
コード例 #18
0
ファイル: ObjectInstance.cs プロジェクト: honestegg/jint
        /// <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.HasValue ? 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.HasValue &&
                !current.Set.HasValue &&
                !current.Value.HasValue)
            {

                return true;
            }

            // Step 6
            if (
                current.Configurable == desc.Configurable &&
                current.Writable == desc.Writable &&
                current.Enumerable == desc.Enumerable &&

                ((!current.Get.HasValue && !desc.Get.HasValue) || (current.Get.HasValue && desc.Get.HasValue && ExpressionInterpreter.SameValue(current.Get.Value, desc.Get.Value))) &&
                ((!current.Set.HasValue && !desc.Set.HasValue) || (current.Set.HasValue && desc.Set.HasValue && ExpressionInterpreter.SameValue(current.Set.Value, desc.Set.Value))) &&
                ((!current.Value.HasValue && !desc.Value.HasValue) || (current.Value.HasValue && desc.Value.HasValue && ExpressionInterpreter.StrictlyEqual(current.Value.Value, desc.Value.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.HasValue && !ExpressionInterpreter.SameValue(desc.Value.Value, current.Value.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.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;
        }
コード例 #19
0
ファイル: ObjectInstance.cs プロジェクト: honestegg/jint
 /// <summary>
 /// Optimized version of [[Put]] when the property is known to be already declared 
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 public void FastSetProperty(string name, PropertyDescriptor value)
 {
     SetOwnProperty(name, value);
 }
コード例 #20
0
ファイル: ObjectInstance.cs プロジェクト: honestegg/jint
 protected virtual void SetOwnProperty(string propertyName, PropertyDescriptor desc)
 {
     EnsureInitialized();
     Properties[propertyName] = desc;
 }
コード例 #21
0
        public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
        {
            var oldLenDesc = _length;
            var oldLen     = (uint)TypeConverter.ToNumber(oldLenDesc.Value);

            uint index;

            if (propertyName.Length == 6 && propertyName == "length")
            {
                var value = desc.Value;
                if (ReferenceEquals(value, null))
                {
                    return(base.DefineOwnProperty("length", desc, throwOnError));
                }

                var  newLenDesc = new PropertyDescriptor(desc);
                uint newLen     = TypeConverter.ToUint32(value);
                if (newLen != TypeConverter.ToNumber(value))
                {
                    ExceptionHelper.ThrowRangeError(_engine);
                }

                newLenDesc.Value = newLen;
                if (newLen >= oldLen)
                {
                    return(base.DefineOwnProperty("length", newLenDesc, throwOnError));
                }

                if (!oldLenDesc.Writable)
                {
                    if (throwOnError)
                    {
                        ExceptionHelper.ThrowTypeError(_engine);
                    }

                    return(false);
                }

                bool newWritable;
                if (!newLenDesc.WritableSet || newLenDesc.Writable)
                {
                    newWritable = true;
                }
                else
                {
                    newWritable         = false;
                    newLenDesc.Writable = true;
                }

                var succeeded = base.DefineOwnProperty("length", newLenDesc, throwOnError);
                if (!succeeded)
                {
                    return(false);
                }

                var count = _dense?.Length ?? _sparse.Count;
                if (count < oldLen - newLen)
                {
                    if (_dense != null)
                    {
                        for (uint keyIndex = 0; keyIndex < _dense.Length; ++keyIndex)
                        {
                            if (_dense[keyIndex] == null)
                            {
                                continue;
                            }

                            // is it the index of the array
                            if (keyIndex >= newLen && keyIndex < oldLen)
                            {
                                var deleteSucceeded = DeleteAt(keyIndex);
                                if (!deleteSucceeded)
                                {
                                    newLenDesc.Value = keyIndex + 1;
                                    if (!newWritable)
                                    {
                                        newLenDesc.Writable = false;
                                    }

                                    base.DefineOwnProperty("length", newLenDesc, false);

                                    if (throwOnError)
                                    {
                                        ExceptionHelper.ThrowTypeError(_engine);
                                    }

                                    return(false);
                                }
                            }
                        }
                    }
                    else
                    {
                        // in the case of sparse arrays, treat each concrete element instead of
                        // iterating over all indexes
                        var keys      = new List <uint>(_sparse.Keys);
                        var keysCount = keys.Count;
                        for (var i = 0; i < keysCount; i++)
                        {
                            var keyIndex = keys[i];

                            // is it the index of the array
                            if (keyIndex >= newLen && keyIndex < oldLen)
                            {
                                var deleteSucceeded = Delete(TypeConverter.ToString(keyIndex), false);
                                if (!deleteSucceeded)
                                {
                                    newLenDesc.Value = JsNumber.Create(keyIndex + 1);
                                    if (!newWritable)
                                    {
                                        newLenDesc.Writable = false;
                                    }

                                    base.DefineOwnProperty("length", newLenDesc, false);

                                    if (throwOnError)
                                    {
                                        ExceptionHelper.ThrowTypeError(_engine);
                                    }

                                    return(false);
                                }
                            }
                        }
                    }
                }
                else
                {
                    while (newLen < oldLen)
                    {
                        // algorithm as per the spec
                        oldLen--;
                        var deleteSucceeded = Delete(TypeConverter.ToString(oldLen), false);
                        if (!deleteSucceeded)
                        {
                            newLenDesc.Value = oldLen + 1;
                            if (!newWritable)
                            {
                                newLenDesc.Writable = false;
                            }

                            base.DefineOwnProperty("length", newLenDesc, false);

                            if (throwOnError)
                            {
                                ExceptionHelper.ThrowTypeError(_engine);
                            }

                            return(false);
                        }
                    }
                }

                if (!newWritable)
                {
                    DefineOwnProperty("length", new PropertyDescriptor(value: null, flags: PropertyFlag.WritableSet), false);
                }

                return(true);
            }
            else if (IsArrayIndex(propertyName, out index))
            {
                if (index >= oldLen && !oldLenDesc.Writable)
                {
                    if (throwOnError)
                    {
                        ExceptionHelper.ThrowTypeError(_engine);
                    }

                    return(false);
                }

                var succeeded = base.DefineOwnProperty(propertyName, desc, false);
                if (!succeeded)
                {
                    if (throwOnError)
                    {
                        ExceptionHelper.ThrowTypeError(_engine);
                    }

                    return(false);
                }

                if (index >= oldLen)
                {
                    oldLenDesc.Value = index + 1;
                    base.DefineOwnProperty("length", oldLenDesc, false);
                }

                return(true);
            }

            return(base.DefineOwnProperty(propertyName, desc, throwOnError));
        }
コード例 #22
0
        public static PropertyDescriptor ToPropertyDescriptor(Engine engine, JsValue o)
        {
            var obj = o.TryCast <ObjectInstance>();

            if (obj == null)
            {
                throw new JavaScriptException(engine.TypeError);
            }

            if ((obj.HasProperty("value") || obj.HasProperty("writable")) &&
                (obj.HasProperty("get") || obj.HasProperty("set")))
            {
                throw new JavaScriptException(engine.TypeError);
            }

            var desc = new PropertyDescriptor();

            if (obj.HasProperty("enumerable"))
            {
                desc.Enumerable = TypeConverter.ToBoolean(obj.Get("enumerable"));
            }

            if (obj.HasProperty("configurable"))
            {
                desc.Configurable = TypeConverter.ToBoolean(obj.Get("configurable"));
            }

            if (obj.HasProperty("value"))
            {
                var value = obj.Get("value");
                desc.Value = value;
            }

            if (obj.HasProperty("writable"))
            {
                desc.Writable = TypeConverter.ToBoolean(obj.Get("writable"));
            }

            if (obj.HasProperty("get"))
            {
                var getter = obj.Get("get");
                if (getter != JsValue.Undefined && getter.TryCast <ICallable>() == null)
                {
                    throw new JavaScriptException(engine.TypeError);
                }
                desc.Get = getter;
            }

            if (obj.HasProperty("set"))
            {
                var setter = obj.Get("set");
                if (setter != Native.Undefined.Instance && setter.TryCast <ICallable>() == null)
                {
                    throw new JavaScriptException(engine.TypeError);
                }
                desc.Set = setter;
            }

            if (desc.Get.HasValue || desc.Get.HasValue)
            {
                if (desc.Value.HasValue || desc.Writable.HasValue)
                {
                    throw new JavaScriptException(engine.TypeError);
                }
            }

            return(desc);
        }
コード例 #23
0
ファイル: ArrayInstance.cs プロジェクト: hnafar/jint
        protected override void SetOwnProperty(string propertyName, PropertyDescriptor desc)
        {
            uint index;
            if (IsArrayIndex(propertyName, out index))
            {
                _array[index] = desc;
            }
            else
            {
                if(propertyName == "length")
                {
                    _length = desc;
                }

                base.SetOwnProperty(propertyName, desc);
            }
        }
コード例 #24
0
ファイル: ArrayInstance.cs プロジェクト: BusinessActs/jint
        public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
        {
            var oldLenDesc = GetOwnProperty("length");
            var oldLen = TypeConverter.ToNumber(oldLenDesc.Value.Value);
            if (propertyName == "length")
            {
                if (!desc.Value.HasValue)
                {
                    return base.DefineOwnProperty("length", desc, throwOnError);
                }

                var newLenDesc = new PropertyDescriptor(desc);
                uint newLen = TypeConverter.ToUint32(desc.Value.Value);
                if (newLen != TypeConverter.ToNumber(desc.Value.Value))
                {
                    throw new JavaScriptException(_engine.RangeError);
                }

                newLenDesc.Value = newLen;
                if (newLen >= oldLen)
                {
                    return base.DefineOwnProperty("length", newLenDesc, throwOnError);
                }
                if (!oldLenDesc.Writable.Value.AsBoolean())
                {
                    if (throwOnError)
                    {
                        throw new JavaScriptException(_engine.TypeError);
                    }

                    return false;
                }
                bool newWritable;
                if (!newLenDesc.Writable.HasValue || newLenDesc.Writable.Value.AsBoolean())
                {
                    newWritable = true;
                }
                else
                {
                    newWritable = false;
                    newLenDesc.Writable = true;
                }
                
                var succeeded = base.DefineOwnProperty("length", newLenDesc, throwOnError);
                if (!succeeded)
                {
                    return false;
                }
                // in the case of sparse arrays, treat each concrete element instead of
                // iterating over all indexes

                if (Properties.Count < oldLen - newLen)
                {
                    var keys = Properties.Keys.ToArray();
                    foreach (var key in keys)
                    {
                        uint index;
                        // is it the index of the array
                        if (uint.TryParse(key, out index) && index >= newLen && index < oldLen)
                        {
                            var deleteSucceeded = Delete(key, false);
                            if (!deleteSucceeded)
                            {
                                newLenDesc.Value = new JsValue(index + 1);
                                if (!newWritable)
                                {
                                    newLenDesc.Writable = JsValue.False;
                                }
                                base.DefineOwnProperty("length", newLenDesc, false);
                                if (throwOnError)
                                {
                                    throw new JavaScriptException(_engine.TypeError);
                                }

                                return false;
                            }
                        }
                    }
                }
                else
                {
                    while (newLen < oldLen)
                    {
                        // algorithm as per the spec
                        oldLen--;
                        var deleteSucceeded = Delete(TypeConverter.ToString(oldLen), false);
                        if (!deleteSucceeded)
                        {
                            newLenDesc.Value = oldLen + 1;
                            if (!newWritable)
                            {
                                newLenDesc.Writable = false;
                            }
                            base.DefineOwnProperty("length", newLenDesc, false);
                            if (throwOnError)
                            {
                                throw new JavaScriptException(_engine.TypeError);
                            }

                            return false;
                        }
                    }
                }
                if (!newWritable)
                {
                    DefineOwnProperty("length", new PropertyDescriptor(value: null, writable: false, enumerable: null, configurable: null), false);
                }
                return true;
            }
            else if (IsArrayIndex(propertyName))
            {
                var index = TypeConverter.ToUint32(propertyName);
                if (index >= oldLen && !oldLenDesc.Writable.Value.AsBoolean())
                {
                    if (throwOnError)
                    {
                        throw new JavaScriptException(_engine.TypeError);
                    }

                    return false;
                }
                var succeeded = base.DefineOwnProperty(propertyName, desc, false);
                if (!succeeded)
                {
                    if (throwOnError)
                    {
                        throw new JavaScriptException(_engine.TypeError);
                    }

                    return false;
                }
                if (index >= oldLen)
                {
                    oldLenDesc.Value = index + 1;
                    base.DefineOwnProperty("length", oldLenDesc, false);
                }
                return true;
            }

            return base.DefineOwnProperty(propertyName, desc, throwOnError);
        }
コード例 #25
0
ファイル: ArrayInstance.cs プロジェクト: Shuffle-Game/jint
        /// Implementation from ObjectInstance official specs as the one 
        /// in ObjectInstance is optimized for the general case and wouldn't work 
        /// for arrays
        public override void Put(string propertyName, JsValue value, bool throwOnError)
        {
            if (!CanPut(propertyName))
            {
                if (throwOnError)
                {
                    throw new JavaScriptException(Engine.TypeError);
                }

                return;
            }
            if (InternalArray != null)
            {
                int ind;
                if (int.TryParse(propertyName, out ind))
                {
                    object val;
                    switch (value.Type)
                    {
                        case Types.Undefined:
                            val = null;
                            break;
                        case Types.Null:
                            val = null;
                            break;
                        case Types.Boolean:
                            val = value.AsBoolean();
                            break;
                        case Types.String:
                            val = value.AsString();
                            break;
                        case Types.Number:
                            val = value.AsNumber();
                            break;
                        case Types.Object:
                            val = value;
                            var ow = ((JsValue)val).AsObject() as ObjectWrapper;
                            if (ow != null)
                            {
                                val = ow.Target;
                            }
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                    if (ind >= InternalArray.Count)
                    {
                        for (int i = InternalArray.Count; i <= ind; i++)
                        {
                            if (val != null)
                                InternalArray.Add(GetDefault(val.GetType()));
                            else
                                InternalArray.Add(null);
                        }
                    }

                    InternalArray[ind] = val;
                }
            }

            var ownDesc = GetOwnProperty(propertyName);

            if (ownDesc.IsDataDescriptor())
            {
                var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable: null, configurable: null);
                DefineOwnProperty(propertyName, valueDesc, throwOnError);
                return;
            }

            // property is an accessor or inherited
            var desc = GetProperty(propertyName);

            if (desc.IsAccessorDescriptor())
            {
                var setter = desc.Set.Value.TryCast<ICallable>();
                setter.Call(new JsValue(this), new[] { value });
            }
            else
            {
                var newDesc = new PropertyDescriptor(value, true, true, true);
                DefineOwnProperty(propertyName, newDesc, throwOnError);
            }
        }