|
@@ -1,6 +1,4 @@
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
-using Jint.Native.Date;
|
|
|
|
-using Jint.Native.String;
|
|
|
|
using Jint.Runtime;
|
|
using Jint.Runtime;
|
|
using Jint.Runtime.Descriptors;
|
|
using Jint.Runtime.Descriptors;
|
|
|
|
|
|
@@ -11,7 +9,7 @@ namespace Jint.Native.Object
|
|
public ObjectInstance(Engine engine)
|
|
public ObjectInstance(Engine engine)
|
|
{
|
|
{
|
|
Engine = engine;
|
|
Engine = engine;
|
|
- Properties = new Dictionary<string, PropertyDescriptor>();
|
|
|
|
|
|
+ Properties = new MruPropertyCache2<string, PropertyDescriptor>();
|
|
}
|
|
}
|
|
|
|
|
|
public Engine Engine { get; set; }
|
|
public Engine Engine { get; set; }
|
|
@@ -69,7 +67,7 @@ namespace Jint.Native.Object
|
|
var callable = getter.TryCast<ICallable>();
|
|
var callable = getter.TryCast<ICallable>();
|
|
return callable.Call(this, Arguments.Empty);
|
|
return callable.Call(this, Arguments.Empty);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Returns the Property Descriptor of the named
|
|
/// Returns the Property Descriptor of the named
|
|
/// own property of this object, or undefined if
|
|
/// own property of this object, or undefined if
|
|
@@ -150,9 +148,13 @@ namespace Jint.Native.Object
|
|
|
|
|
|
if (ownDesc.IsDataDescriptor())
|
|
if (ownDesc.IsDataDescriptor())
|
|
{
|
|
{
|
|
- var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable:null, configurable:null);
|
|
|
|
- DefineOwnProperty(propertyName, valueDesc, throwOnError);
|
|
|
|
|
|
+ ownDesc.Value = value;
|
|
return;
|
|
return;
|
|
|
|
+
|
|
|
|
+ // as per specification
|
|
|
|
+ // var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable: null, configurable: null);
|
|
|
|
+ // DefineOwnProperty(propertyName, valueDesc, throwOnError);
|
|
|
|
+ // return;
|
|
}
|
|
}
|
|
|
|
|
|
// property is an accessor or inherited
|
|
// property is an accessor or inherited
|
|
@@ -194,7 +196,7 @@ namespace Jint.Native.Object
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- return desc.Writable.HasValue && desc.Writable.Value.AsBoolean();
|
|
|
|
|
|
+ return desc.Writable.HasValue && desc.Writable.Value;
|
|
}
|
|
}
|
|
|
|
|
|
if (Prototype == null)
|
|
if (Prototype == null)
|
|
@@ -225,7 +227,7 @@ namespace Jint.Native.Object
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- return inherited.Writable.HasValue && inherited.Writable.Value.AsBoolean();
|
|
|
|
|
|
+ return inherited.Writable.HasValue && inherited.Writable.Value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -258,7 +260,7 @@ namespace Jint.Native.Object
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (desc.Configurable.HasValue && desc.Configurable.Value.AsBoolean())
|
|
|
|
|
|
+ if (desc.Configurable.HasValue && desc.Configurable.Value)
|
|
{
|
|
{
|
|
Properties.Remove(propertyName);
|
|
Properties.Remove(propertyName);
|
|
return true;
|
|
return true;
|
|
@@ -347,7 +349,11 @@ namespace Jint.Native.Object
|
|
public virtual bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
|
|
public virtual bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
|
|
{
|
|
{
|
|
var current = GetOwnProperty(propertyName);
|
|
var current = GetOwnProperty(propertyName);
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if (current == desc) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (current == PropertyDescriptor.Undefined)
|
|
if (current == PropertyDescriptor.Undefined)
|
|
{
|
|
{
|
|
if (!Extensible)
|
|
if (!Extensible)
|
|
@@ -366,13 +372,17 @@ namespace Jint.Native.Object
|
|
Properties[propertyName] = new PropertyDescriptor(desc)
|
|
Properties[propertyName] = new PropertyDescriptor(desc)
|
|
{
|
|
{
|
|
Value = desc.Value.HasValue ? desc.Value : JsValue.Undefined,
|
|
Value = desc.Value.HasValue ? desc.Value : JsValue.Undefined,
|
|
- Writable = desc.Writable.HasValue ? desc.Writable : false
|
|
|
|
|
|
+ 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
|
|
else
|
|
{
|
|
{
|
|
Properties[propertyName] = new PropertyDescriptor(desc)
|
|
Properties[propertyName] = new PropertyDescriptor(desc)
|
|
{
|
|
{
|
|
|
|
+ Get = desc.Get,
|
|
|
|
+ Set = desc.Set,
|
|
Enumerable = desc.Enumerable.HasValue ? desc.Enumerable : false,
|
|
Enumerable = desc.Enumerable.HasValue ? desc.Enumerable : false,
|
|
Configurable = desc.Configurable.HasValue ? desc.Configurable : false,
|
|
Configurable = desc.Configurable.HasValue ? desc.Configurable : false,
|
|
};
|
|
};
|
|
@@ -390,76 +400,26 @@ namespace Jint.Native.Object
|
|
!current.Set.HasValue &&
|
|
!current.Set.HasValue &&
|
|
!current.Value.HasValue)
|
|
!current.Value.HasValue)
|
|
{
|
|
{
|
|
|
|
+
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
// Step 6
|
|
// 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)
|
|
|
|
- {
|
|
|
|
|
|
+ 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;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean())
|
|
|
|
|
|
+ if (!current.Configurable.HasValue || !current.Configurable.Value)
|
|
{
|
|
{
|
|
- if (desc.Configurable.HasValue && desc.Configurable.Value.AsBoolean())
|
|
|
|
|
|
+ if (desc.Configurable.HasValue && desc.Configurable.Value)
|
|
{
|
|
{
|
|
if (throwOnError)
|
|
if (throwOnError)
|
|
{
|
|
{
|
|
@@ -485,7 +445,7 @@ namespace Jint.Native.Object
|
|
|
|
|
|
if (current.IsDataDescriptor() != desc.IsDataDescriptor())
|
|
if (current.IsDataDescriptor() != desc.IsDataDescriptor())
|
|
{
|
|
{
|
|
- if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean())
|
|
|
|
|
|
+ if (!current.Configurable.HasValue || !current.Configurable.Value)
|
|
{
|
|
{
|
|
if (throwOnError)
|
|
if (throwOnError)
|
|
{
|
|
{
|
|
@@ -500,8 +460,8 @@ namespace Jint.Native.Object
|
|
Properties[propertyName] = current = new PropertyDescriptor(
|
|
Properties[propertyName] = current = new PropertyDescriptor(
|
|
get: Undefined.Instance,
|
|
get: Undefined.Instance,
|
|
set: Undefined.Instance,
|
|
set: Undefined.Instance,
|
|
- enumerable: current.Enumerable.HasValue && current.Enumerable.Value.AsBoolean(),
|
|
|
|
- configurable: current.Configurable.HasValue && current.Configurable.Value.AsBoolean()
|
|
|
|
|
|
+ enumerable: current.Enumerable,
|
|
|
|
+ configurable: current.Configurable
|
|
);
|
|
);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
@@ -509,16 +469,16 @@ namespace Jint.Native.Object
|
|
Properties[propertyName] = current = new PropertyDescriptor(
|
|
Properties[propertyName] = current = new PropertyDescriptor(
|
|
value: Undefined.Instance,
|
|
value: Undefined.Instance,
|
|
writable: null,
|
|
writable: null,
|
|
- enumerable: current.Enumerable.HasValue && current.Enumerable.Value.AsBoolean(),
|
|
|
|
- configurable: current.Configurable.HasValue && current.Configurable.Value.AsBoolean()
|
|
|
|
|
|
+ enumerable: current.Enumerable,
|
|
|
|
+ configurable: current.Configurable
|
|
);
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (current.IsDataDescriptor() && desc.IsDataDescriptor())
|
|
else if (current.IsDataDescriptor() && desc.IsDataDescriptor())
|
|
{
|
|
{
|
|
- if (!current.Configurable.HasValue || current.Configurable.Value.AsBoolean() == false)
|
|
|
|
|
|
+ if (!current.Configurable.HasValue || current.Configurable.Value == false)
|
|
{
|
|
{
|
|
- if (!current.Writable.HasValue || !current.Writable.Value.AsBoolean() && desc.Writable.HasValue && desc.Writable.Value.AsBoolean())
|
|
|
|
|
|
+ if (!current.Writable.HasValue || !current.Writable.Value && desc.Writable.HasValue && desc.Writable.Value)
|
|
{
|
|
{
|
|
if (throwOnError)
|
|
if (throwOnError)
|
|
{
|
|
{
|
|
@@ -528,9 +488,9 @@ namespace Jint.Native.Object
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!current.Writable.Value.AsBoolean())
|
|
|
|
|
|
+ if (!current.Writable.Value)
|
|
{
|
|
{
|
|
- if (desc.Value.HasValue && !valueIsSame)
|
|
|
|
|
|
+ if (desc.Value.HasValue && !ExpressionInterpreter.SameValue(desc.Value.Value, current.Value.Value))
|
|
{
|
|
{
|
|
if (throwOnError)
|
|
if (throwOnError)
|
|
{
|
|
{
|
|
@@ -544,7 +504,7 @@ namespace Jint.Native.Object
|
|
}
|
|
}
|
|
else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor())
|
|
else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor())
|
|
{
|
|
{
|
|
- if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean())
|
|
|
|
|
|
+ if (!current.Configurable.HasValue || !current.Configurable.Value)
|
|
{
|
|
{
|
|
if ((desc.Set.HasValue && !ExpressionInterpreter.SameValue(desc.Set.Value, current.Set.HasValue ? current.Set.Value : Undefined.Instance))
|
|
if ((desc.Set.HasValue && !ExpressionInterpreter.SameValue(desc.Set.Value, current.Set.HasValue ? current.Set.Value : Undefined.Instance))
|
|
||
|
|
||
|