123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- using Jint.Native;
- using Jint.Native.Global;
- using Jint.Runtime.Descriptors;
- using Jint.Runtime.Descriptors.Specialized;
- using Jint.Runtime.Interop;
- using Jint.Tests.TestClasses;
- namespace Jint.Tests.Runtime;
- public class PropertyDescriptorTests
- {
- public class TestClass
- {
- public static readonly TestClass Instance = new TestClass();
- public string Method() => "Method";
- public class NestedType { }
- public readonly int fieldReadOnly = 8;
- public int field = 42;
- public string PropertyReadOnly => "PropertyReadOnly";
- public string PropertyWriteOnly { set { } }
- public string PropertyReadWrite { get; set; } = "PropertyReadWrite";
- public IndexedPropertyReadOnly<int, int> IndexerReadOnly { get; }
- = new((idx) => 42);
- public IndexedPropertyWriteOnly<int, int> IndexerWriteOnly { get; }
- = new((idx, v) => { });
- public IndexedProperty<int, int> IndexerReadWrite { get; }
- = new((idx) => 42, (idx, v) => { });
- }
- private readonly Engine _engine;
- private readonly bool checkType = true;
- public PropertyDescriptorTests()
- {
- _engine = new Engine(cfg => cfg.AllowClr(
- typeof(TestClass).Assembly,
- typeof(Console).Assembly,
- typeof(File).Assembly))
- .SetValue("log", new Action<object>(Console.WriteLine))
- .SetValue("assert", new Action<bool>(Assert.True))
- .SetValue("equal", new Action<object, object>(Assert.Equal))
- .SetValue("testClass", TestClass.Instance)
- ;
- }
- [Fact]
- public void PropertyDescriptorReadOnly()
- {
- var pd = _engine.Evaluate("""
- Object.defineProperty({}, 'value', {
- value: 42,
- writable: false
- })
- """).AsObject().GetOwnProperty("value");
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(true, pd.IsDataDescriptor());
- Assert.Equal(false, pd.Writable);
- Assert.Null(pd.Get);
- Assert.Null(pd.Set);
- }
- [Fact]
- public void PropertyDescriptorReadWrite()
- {
- var pd = _engine.Evaluate("""
- Object.defineProperty({}, 'value', {
- value: 42,
- writable: true
- })
- """).AsObject().GetOwnProperty("value");
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(true, pd.IsDataDescriptor());
- Assert.Equal(true, pd.Writable);
- Assert.Null(pd.Get);
- Assert.Null(pd.Set);
- }
- [Fact]
- public void UndefinedPropertyDescriptor()
- {
- var pd = PropertyDescriptor.Undefined;
- // PropertyDescriptor.UndefinedPropertyDescriptor is private
- //if (checkType) Assert.IsType<PropertyDescriptor.UndefinedPropertyDescriptor>(pd);
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void AllForbiddenDescriptor()
- {
- var pd = _engine.Evaluate("Object.getPrototypeOf('s')").AsObject().GetOwnProperty("length");
- if (checkType) Assert.IsType<PropertyDescriptor.AllForbiddenDescriptor>(pd);
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(true, pd.IsDataDescriptor());
- }
- [Fact]
- public void LazyPropertyDescriptor()
- {
- var pd = _engine.Evaluate("globalThis").AsObject().GetOwnProperty("decodeURI");
- if (checkType)
- {
- Assert.IsType<LazyPropertyDescriptor<GlobalObject>>(pd);
- }
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(true, pd.IsDataDescriptor());
- }
- [Fact]
- public void ThrowerPropertyDescriptor()
- {
- var pd = _engine.Evaluate("Object.getPrototypeOf(function() {})").AsObject().GetOwnProperty("arguments");
- if (checkType) Assert.IsType<GetSetPropertyDescriptor.ThrowerPropertyDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void GetSetPropertyDescriptorGetOnly()
- {
- var pd = _engine.Evaluate("""
- Object.defineProperty({}, 'value', {
- get() {}
- })
- """).AsObject().GetOwnProperty("value");
- if (checkType) Assert.IsType<GetSetPropertyDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- Assert.NotNull(pd.Get);
- Assert.Null(pd.Set);
- }
- [Fact]
- public void GetSetPropertyDescriptorSetOnly()
- {
- var pd = _engine.Evaluate("""
- Object.defineProperty({}, 'value', {
- set() {}
- })
- """).AsObject().GetOwnProperty("value");
- if (checkType) Assert.IsType<GetSetPropertyDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- Assert.Null(pd.Get);
- Assert.NotNull(pd.Set);
- }
- [Fact]
- public void GetSetPropertyDescriptorGetSet()
- {
- var pd = _engine.Evaluate("""
- Object.defineProperty({}, 'value', {
- get() {},
- set() {}
- })
- """).AsObject().GetOwnProperty("value");
- if (checkType) Assert.IsType<GetSetPropertyDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- Assert.NotNull(pd.Get);
- Assert.NotNull(pd.Set);
- }
- [Fact]
- public void ClrAccessDescriptor()
- {
- JsValue ExtractClrAccessDescriptor(JsValue jsArugments)
- {
- var pd = ((JsArguments) jsArugments).ParameterMap.GetOwnProperty("0");
- return ObjectWrapper.Create(_engine, pd);
- }
- _engine.SetValue("ExtractClrAccessDescriptor", ExtractClrAccessDescriptor);
- var pdobj = _engine.Evaluate("""
- (function(a) {
- return ExtractClrAccessDescriptor(arguments);
- })(42)
- """);
- var pd = (PropertyDescriptor) ((ObjectWrapper) pdobj).Target;
- if (checkType) Assert.IsType<ClrAccessDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void PropertyDescriptorMethod()
- {
- var pdMethod = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'Method')");
- CheckPropertyDescriptor(pdMethod, false, false, false, true, false, false);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("Method");
- // use PropertyDescriptor to wrap method directly
- //if (checkType) Assert.IsType<PropertyDescriptor>(pd);
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(true, pd.IsDataDescriptor());
- }
- [Fact]
- public void PropertyDescriptorNestedType()
- {
- var pdMethod = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'NestedType')");
- CheckPropertyDescriptor(pdMethod, false, false, false, true, false, false);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("NestedType");
- // use PropertyDescriptor to wrap nested type directly
- //if (checkType) Assert.IsType<PropertyDescriptor>(pd);
- Assert.Equal(false, pd.IsAccessorDescriptor());
- Assert.Equal(true, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorFieldReadOnly()
- {
- var pdField = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'fieldReadOnly')");
- CheckPropertyDescriptor(pdField, false, true, false, false, true, false);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("fieldReadOnly");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorField()
- {
- var pdField = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'field')");
- CheckPropertyDescriptor(pdField, false, true, true, false, true, true);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("field");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorPropertyReadOnly()
- {
- var pdPropertyReadOnly = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'PropertyReadOnly')");
- CheckPropertyDescriptor(pdPropertyReadOnly, false, true, false, false, true, false);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("PropertyReadOnly");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorPropertyWriteOnly()
- {
- var pdPropertyWriteOnly = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'PropertyWriteOnly')");
- CheckPropertyDescriptor(pdPropertyWriteOnly, false, true, true, false, false, true);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("PropertyWriteOnly");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorPropertyReadWrite()
- {
- var pdPropertyReadWrite = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'PropertyReadWrite')");
- CheckPropertyDescriptor(pdPropertyReadWrite, false, true, true, false, true, true);
- var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("PropertyReadWrite");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorIndexerReadOnly()
- {
- var pdIndexerReadOnly = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass.IndexerReadOnly, '1')");
- CheckPropertyDescriptor(pdIndexerReadOnly, false, true, false, false, true, false);
- var pd1 = _engine.Evaluate("testClass.IndexerReadOnly");
- var pd = pd1.AsObject().GetOwnProperty("1");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorIndexerWriteOnly()
- {
- var pdIndexerWriteOnly = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass.IndexerWriteOnly, '1')");
- CheckPropertyDescriptor(pdIndexerWriteOnly, false, true, true, false, false, true);
- var pd = _engine.Evaluate("testClass.IndexerWriteOnly").AsObject().GetOwnProperty("1");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- [Fact]
- public void ReflectionDescriptorIndexerReadWrite()
- {
- var pdIndexerReadWrite = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass.IndexerReadWrite, 1)");
- CheckPropertyDescriptor(pdIndexerReadWrite, false, true, true, false, true, true);
- var pd = _engine.Evaluate("testClass.IndexerReadWrite").AsObject().GetOwnProperty("1");
- if (checkType) Assert.IsType<ReflectionDescriptor>(pd);
- Assert.Equal(true, pd.IsAccessorDescriptor());
- Assert.Equal(false, pd.IsDataDescriptor());
- }
- private void CheckPropertyDescriptor(
- JsValue jsPropertyDescriptor,
- bool configurable,
- bool enumerable,
- bool writable,
- bool hasValue,
- bool hasGet,
- bool hasSet
- )
- {
- var pd = jsPropertyDescriptor.AsObject();
- Assert.Equal(configurable, pd["configurable"].AsBoolean());
- Assert.Equal(enumerable, pd["enumerable"].AsBoolean());
- if (writable)
- {
- var writableActual = pd["writable"];
- if (!writableActual.IsUndefined())
- {
- Assert.True(writableActual.AsBoolean());
- }
- }
- Assert.Equal(hasValue, !pd["value"].IsUndefined());
- Assert.Equal(hasGet, !pd["get"].IsUndefined());
- Assert.Equal(hasSet, !pd["set"].IsUndefined());
- }
- [Fact]
- public void DefinePropertyFromAccesorToData()
- {
- var pd = _engine.Evaluate("""
- let o = {};
- Object.defineProperty(o, 'foo', {
- get() { return 1; },
- configurable: true
- });
- Object.defineProperty(o, 'foo', {
- value: 101
- });
- return Object.getOwnPropertyDescriptor(o, 'foo');
- """);
- Assert.Equal(101, pd.AsObject().Get("value").AsInteger());
- CheckPropertyDescriptor(pd, true, false, false, true, false, false);
- }
- }
|