ProxyTests.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. namespace Jint.Tests.Runtime;
  2. public class ProxyTests
  3. {
  4. private readonly Engine _engine;
  5. public ProxyTests()
  6. {
  7. _engine = new Engine()
  8. .SetValue("equal", new Action<object, object>(Assert.Equal));
  9. }
  10. [Fact]
  11. public void ProxyCanBeRevokedWithoutContext()
  12. {
  13. _engine.Execute(@"
  14. var revocable = Proxy.revocable({}, {});
  15. var revoke = revocable.revoke;
  16. revoke.call(null);
  17. ");
  18. }
  19. [Fact]
  20. public void ProxyToStringUseTarget()
  21. {
  22. _engine.Execute(@"
  23. const targetWithToString = {toString: () => 'target'}
  24. ");
  25. Assert.Equal("target", _engine.Evaluate("new Proxy(targetWithToString, {}).toString()").AsString());
  26. Assert.Equal("target", _engine.Evaluate("`${new Proxy(targetWithToString, {})}`").AsString());
  27. }
  28. [Fact]
  29. public void ProxyToStringUseHandler()
  30. {
  31. _engine.Execute(@"
  32. const handler = { get: (target, prop, receiver) => prop === 'toString' ? () => 'handler' : Reflect.get(target, prop, receiver) }
  33. const targetWithToString = {toString: () => 'target'}
  34. ");
  35. Assert.Equal("handler", _engine.Evaluate("new Proxy({}, handler).toString()").AsString());
  36. Assert.Equal("handler", _engine.Evaluate("new Proxy(targetWithToString, handler).toString()").AsString());
  37. Assert.Equal("handler", _engine.Evaluate("`${new Proxy({}, handler)}`").AsString());
  38. Assert.Equal("handler", _engine.Evaluate("`${new Proxy(targetWithToString, handler)}`").AsString());
  39. }
  40. [Fact]
  41. public void ToPropertyDescriptor()
  42. {
  43. const string Script = @"
  44. var get = [];
  45. var p = new Proxy({
  46. enumerable: true, configurable: true, value: true,
  47. writable: true, get: Function(), set: Function()
  48. }, { get: function(o, k) { get.push(k); return o[k]; }});
  49. try {
  50. // This will throw, since it will have true for both ""get"" and ""value"",
  51. // but not before performing a Get on every property.
  52. Object.defineProperty({}, ""foo"", p);
  53. } catch(e) {
  54. return get + '';
  55. }
  56. return 'did not fail as expected'";
  57. Assert.Equal("enumerable,configurable,value,writable,get,set", _engine.Evaluate(Script));
  58. }
  59. [Fact]
  60. public void DefineProperties()
  61. {
  62. const string Script = @"
  63. // Object.defineProperties -> Get -> [[Get]]
  64. var get = [];
  65. var p = new Proxy({foo:{}, bar:{}}, { get: function(o, k) { get.push(k); return o[k]; }});
  66. Object.defineProperties({}, p);
  67. return get + '';";
  68. Assert.Equal("foo,bar", _engine.Evaluate(Script));
  69. }
  70. [Fact]
  71. public void GetHandlerInstancesOfProxies()
  72. {
  73. const string Script = @"
  74. var proxied = { };
  75. var proxy = Object.create(new Proxy(proxied, {
  76. get: function (t, k, r) {
  77. equal(t, proxied); equal('foo', k); equal(proxy, r);
  78. return t === proxied && k === 'foo' && r === proxy && 5;
  79. }
  80. }));
  81. equal(5, proxy.foo);";
  82. _engine.Execute(Script);
  83. }
  84. [Fact]
  85. public void SetHandlerInvariants()
  86. {
  87. const string Script = @"
  88. var passed = false;
  89. var proxied = { };
  90. var proxy = new Proxy(proxied, {
  91. get: function () {
  92. passed = true;
  93. return 4;
  94. }
  95. });
  96. // The value reported for a property must be the same as the value of the corresponding
  97. // target object property if the target object property is a non-writable,
  98. // non-configurable own data property.
  99. Object.defineProperty(proxied, ""foo"", { value: 5, enumerable: true });
  100. try {
  101. proxy.foo;
  102. return false;
  103. }
  104. catch(e) {}
  105. // The value reported for a property must be undefined if the corresponding target
  106. // object property is a non-configurable own accessor property that has undefined
  107. // as its [[Get]] attribute.
  108. Object.defineProperty(proxied, ""bar"",
  109. { set: function(){}, enumerable: true });
  110. try {
  111. proxy.bar;
  112. return false;
  113. }
  114. catch(e) {}
  115. return passed;";
  116. Assert.True(_engine.Evaluate(Script).AsBoolean());
  117. }
  118. [Fact]
  119. public void ApplyHandlerInvariant()
  120. {
  121. const string Script = @"
  122. var passed = false;
  123. new Proxy(function(){}, {
  124. apply: function () { passed = true; }
  125. })();
  126. // A Proxy exotic object only has a [[Call]] internal method if the
  127. // initial value of its [[ProxyTarget]] internal slot is an object
  128. // that has a [[Call]] internal method.
  129. try {
  130. new Proxy({}, {
  131. apply: function () {}
  132. })();
  133. return false;
  134. } catch(e) {}
  135. return passed;";
  136. Assert.True(_engine.Evaluate(Script).AsBoolean());
  137. }
  138. [Fact]
  139. public void ConstructHandlerInvariant()
  140. {
  141. const string Script = @"
  142. var passed = false;
  143. new Proxy({},{});
  144. // A Proxy exotic object only has a [[Construct]] internal method if the
  145. // initial value of its [[ProxyTarget]] internal slot is an object
  146. // that has a [[Construct]] internal method.
  147. try {
  148. new new Proxy({}, {
  149. construct: function (t, args) {
  150. return {};
  151. }
  152. })();
  153. return false;
  154. } catch(e) {}
  155. // The result of [[Construct]] must be an Object.
  156. try {
  157. new new Proxy(function(){}, {
  158. construct: function (t, args) {
  159. passed = true;
  160. return 5;
  161. }
  162. })();
  163. return false;
  164. } catch(e) {}
  165. return passed;";
  166. Assert.True(_engine.Evaluate(Script).AsBoolean());
  167. }
  168. }