|
@@ -25,15 +25,19 @@ namespace Jint.Native.Object
|
|
{
|
|
{
|
|
const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
|
|
const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
|
|
const PropertyFlag lengthFlags = PropertyFlag.Configurable;
|
|
const PropertyFlag lengthFlags = PropertyFlag.Configurable;
|
|
- var properties = new PropertyDictionary(8, checkExistingKeys: false)
|
|
|
|
|
|
+ var properties = new PropertyDictionary(12, checkExistingKeys: false)
|
|
{
|
|
{
|
|
["constructor"] = new PropertyDescriptor(_constructor, propertyFlags),
|
|
["constructor"] = new PropertyDescriptor(_constructor, propertyFlags),
|
|
|
|
+ ["__defineGetter__"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "__defineGetter__", DefineGetter, 2, lengthFlags), propertyFlags),
|
|
|
|
+ ["__defineSetter__"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "__defineSetter__", DefineSetter, 2, lengthFlags), propertyFlags),
|
|
|
|
+ ["__lookupGetter__"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "__lookupGetter__", LookupGetter, 1, lengthFlags), propertyFlags),
|
|
|
|
+ ["__lookupSetter__"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "__lookupSetter__", LookupSetter, 1, lengthFlags), propertyFlags),
|
|
["__proto__"] = new GetSetPropertyDescriptor(
|
|
["__proto__"] = new GetSetPropertyDescriptor(
|
|
new ClrFunctionInstance(Engine, "get __proto__", (thisObject, _) => TypeConverter.ToObject(_realm, thisObject).GetPrototypeOf() ?? Null, 0, lengthFlags),
|
|
new ClrFunctionInstance(Engine, "get __proto__", (thisObject, _) => TypeConverter.ToObject(_realm, thisObject).GetPrototypeOf() ?? Null, 0, lengthFlags),
|
|
new ClrFunctionInstance(Engine, "set __proto__", (thisObject, arguments) =>
|
|
new ClrFunctionInstance(Engine, "set __proto__", (thisObject, arguments) =>
|
|
{
|
|
{
|
|
TypeConverter.CheckObjectCoercible(_engine, thisObject);
|
|
TypeConverter.CheckObjectCoercible(_engine, thisObject);
|
|
-
|
|
|
|
|
|
+
|
|
var proto = arguments.At(0);
|
|
var proto = arguments.At(0);
|
|
if (!proto.IsObject() && !proto.IsNull() || thisObject is not ObjectInstance objectInstance)
|
|
if (!proto.IsObject() && !proto.IsNull() || thisObject is not ObjectInstance objectInstance)
|
|
{
|
|
{
|
|
@@ -44,7 +48,7 @@ namespace Jint.Native.Object
|
|
{
|
|
{
|
|
ExceptionHelper.ThrowTypeError(_realm, "Invalid prototype");
|
|
ExceptionHelper.ThrowTypeError(_realm, "Invalid prototype");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
return Undefined;
|
|
return Undefined;
|
|
}, 0, lengthFlags),
|
|
}, 0, lengthFlags),
|
|
enumerable: false, configurable: true),
|
|
enumerable: false, configurable: true),
|
|
@@ -57,7 +61,7 @@ namespace Jint.Native.Object
|
|
};
|
|
};
|
|
SetProperties(properties);
|
|
SetProperties(properties);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
|
|
public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
|
|
{
|
|
{
|
|
TrackChanges(property);
|
|
TrackChanges(property);
|
|
@@ -83,6 +87,104 @@ namespace Jint.Native.Object
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// https://tc39.es/ecma262/#sec-object.prototype.__defineGetter__
|
|
|
|
+ /// </summary>
|
|
|
|
+ private JsValue DefineGetter(JsValue thisObject, JsValue[] arguments)
|
|
|
|
+ {
|
|
|
|
+ var o = TypeConverter.ToObject(_realm, thisObject);
|
|
|
|
+ var p = arguments.At(0);
|
|
|
|
+ var getter = arguments.At(1);
|
|
|
|
+
|
|
|
|
+ if (!getter.IsCallable)
|
|
|
|
+ {
|
|
|
|
+ ExceptionHelper.ThrowTypeError(_realm, "Target is not callable");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var desc = new GetSetPropertyDescriptor(getter, null, enumerable: true, configurable: true);
|
|
|
|
+ var key = TypeConverter.ToPropertyKey(p);
|
|
|
|
+ o.DefinePropertyOrThrow(key, desc);
|
|
|
|
+
|
|
|
|
+ return Undefined;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// https://tc39.es/ecma262/#sec-object.prototype.__defineSetter__
|
|
|
|
+ /// </summary>
|
|
|
|
+ private JsValue DefineSetter(JsValue thisObject, JsValue[] arguments)
|
|
|
|
+ {
|
|
|
|
+ var o = TypeConverter.ToObject(_realm, thisObject);
|
|
|
|
+ var p = arguments.At(0);
|
|
|
|
+ var setter = arguments.At(1);
|
|
|
|
+
|
|
|
|
+ if (!setter.IsCallable)
|
|
|
|
+ {
|
|
|
|
+ ExceptionHelper.ThrowTypeError(_realm, "Target is not callable");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var desc = new GetSetPropertyDescriptor(null, setter, enumerable: true, configurable: true);
|
|
|
|
+ var key = TypeConverter.ToPropertyKey(p);
|
|
|
|
+ o.DefinePropertyOrThrow(key, desc);
|
|
|
|
+
|
|
|
|
+ return Undefined;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// https://tc39.es/ecma262/#sec-object.prototype.__lookupGetter__
|
|
|
|
+ /// </summary>
|
|
|
|
+ private JsValue LookupGetter(JsValue thisObject, JsValue[] arguments)
|
|
|
|
+ {
|
|
|
|
+ var o = TypeConverter.ToObject(_realm, thisObject);
|
|
|
|
+ var key = TypeConverter.ToPropertyKey(arguments.At(0));
|
|
|
|
+ while (true)
|
|
|
|
+ {
|
|
|
|
+ var desc = o.GetOwnProperty(key);
|
|
|
|
+ if (!ReferenceEquals(desc, PropertyDescriptor.Undefined))
|
|
|
|
+ {
|
|
|
|
+ if (desc.IsAccessorDescriptor())
|
|
|
|
+ {
|
|
|
|
+ return desc.Get ?? Undefined;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return Undefined;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o = o.GetPrototypeOf();
|
|
|
|
+ if (o is null)
|
|
|
|
+ {
|
|
|
|
+ return Undefined;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// https://tc39.es/ecma262/#sec-object.prototype.__lookupSetter__
|
|
|
|
+ /// </summary>
|
|
|
|
+ private JsValue LookupSetter(JsValue thisObject, JsValue[] arguments)
|
|
|
|
+ {
|
|
|
|
+ var o = TypeConverter.ToObject(_realm, thisObject);
|
|
|
|
+ var key = TypeConverter.ToPropertyKey(arguments.At(0));
|
|
|
|
+ while (true)
|
|
|
|
+ {
|
|
|
|
+ var desc = o.GetOwnProperty(key);
|
|
|
|
+ if (!ReferenceEquals(desc, PropertyDescriptor.Undefined))
|
|
|
|
+ {
|
|
|
|
+ if (desc.IsAccessorDescriptor())
|
|
|
|
+ {
|
|
|
|
+ return desc.Set ?? Undefined;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return Undefined;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o = o.GetPrototypeOf();
|
|
|
|
+ if (o is null)
|
|
|
|
+ {
|
|
|
|
+ return Undefined;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)
|
|
private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)
|
|
{
|
|
{
|
|
var p = TypeConverter.ToPropertyKey(arguments[0]);
|
|
var p = TypeConverter.ToPropertyKey(arguments[0]);
|