ArrayTests.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. using Jint.Native.Array;
  2. namespace Jint.Tests.Runtime
  3. {
  4. public class ArrayTests
  5. {
  6. private readonly Engine _engine;
  7. public ArrayTests()
  8. {
  9. _engine = new Engine()
  10. .SetValue("log", new Action<object>(Console.WriteLine))
  11. .SetValue("assert", new Action<bool>(Assert.True))
  12. .SetValue("equal", new Action<object, object>(Assert.Equal));
  13. }
  14. private void RunTest(string source)
  15. {
  16. _engine.Execute(source);
  17. }
  18. [Fact]
  19. public void ArrayPrototypeToStringWithArray()
  20. {
  21. var result = _engine.Evaluate("Array.prototype.toString.call([1,2,3]);").AsString();
  22. Assert.Equal("1,2,3", result);
  23. }
  24. [Fact]
  25. public void ArrayPrototypeToStringWithNumber()
  26. {
  27. var result = _engine.Evaluate("Array.prototype.toString.call(1);").AsString();
  28. Assert.Equal("[object Number]", result);
  29. }
  30. [Fact]
  31. public void ArrayPrototypeToStringWithObject()
  32. {
  33. var result = _engine.Evaluate("Array.prototype.toString.call({});").AsString();
  34. Assert.Equal("[object Object]", result);
  35. }
  36. [Fact]
  37. public void EmptyStringKey()
  38. {
  39. var result = _engine.Evaluate("var x=[];x[\"\"]=8;x[\"\"];").AsNumber();
  40. Assert.Equal(8, result);
  41. }
  42. [Fact]
  43. public void LargeArraySize()
  44. {
  45. const string code = @"
  46. let arr = [];
  47. for (let i = 0; i < 10000; i++) arr.push(i);
  48. for (let i=0;i<10000;i++) arr.splice(0, 1);
  49. ";
  50. var engine = new Engine();
  51. engine.Execute(code);
  52. }
  53. [Fact]
  54. public void ArrayLengthFromInitialState()
  55. {
  56. var engine = new Engine();
  57. var array = new ArrayInstance(engine, 0);
  58. var length = (int) array.Length;
  59. Assert.Equal(0, length);
  60. }
  61. [Fact]
  62. public void ArraySortIsStable()
  63. {
  64. const string code = @"
  65. var items = [
  66. { name: 'Edward', value: 0 },
  67. { name: 'Sharpe', value: 0 },
  68. { name: 'And', value: 0 },
  69. { name: 'The', value: 1 },
  70. { name: 'Magnetic', value: 0 },
  71. { name: 'Zeros', value: 0 }
  72. ];
  73. // sort by value
  74. function compare(a, b) {
  75. return a.value - b.value;
  76. }
  77. var a = items.sort();
  78. assert(a[0].name == 'Edward');
  79. assert(a[1].name == 'Sharpe');
  80. assert(a[2].name == 'And');
  81. assert(a[3].name == 'The');
  82. assert(a[4].name == 'Magnetic');
  83. assert(a[5].name == 'Zeros');
  84. var a = items.sort(compare);
  85. assert(a[0].name == 'Edward');
  86. assert(a[1].name == 'Sharpe');
  87. assert(a[2].name == 'And');
  88. assert(a[3].name == 'Magnetic');
  89. assert(a[4].name == 'Zeros');
  90. assert(a[5].name == 'The');
  91. ";
  92. _engine.Execute(code);
  93. }
  94. #if !NETCOREAPP
  95. // this test case only triggers on older full framework where the is no checks for infinite comparisons
  96. [Fact]
  97. public void ArraySortShouldObeyExecutionConstraints()
  98. {
  99. const string script = @"
  100. let cases = [5,5];
  101. let latestCase = cases.sort((c1, c2) => c1 > c2 ? -1: 1);";
  102. var engine = new Engine(options => options
  103. .TimeoutInterval(TimeSpan.FromSeconds(1))
  104. );
  105. Assert.Throws<TimeoutException>(() => engine.Evaluate(script));
  106. }
  107. #endif
  108. [Fact]
  109. public void ExtendingArrayAndInstanceOf()
  110. {
  111. const string script = @"
  112. class MyArr extends Array {
  113. constructor(...args) {
  114. super(...args);
  115. }
  116. }";
  117. _engine.Execute(script);
  118. _engine.Evaluate("const a = new MyArr(1,2);");
  119. Assert.True(_engine.Evaluate("a instanceof MyArr").AsBoolean());
  120. }
  121. [Fact]
  122. public void IteratorShouldBeConvertibleToArray()
  123. {
  124. Assert.Equal("hello;again", _engine.Evaluate("Array.from(['hello', 'again'].values()).join(';')"));
  125. Assert.Equal("hello;another", _engine.Evaluate("Array.from(new Map([['hello', 'world'], ['another', 'value']]).keys()).join(';')"));
  126. }
  127. [Fact]
  128. public void ArrayFromShouldNotFlattenInputArray()
  129. {
  130. Assert.Equal("a;b", _engine.Evaluate("[...['a', 'b']].join(';')"));
  131. Assert.Equal("0,a;1,b", _engine.Evaluate("[...['a', 'b'].entries()].join(';')"));
  132. Assert.Equal("0,c;1,d", _engine.Evaluate("Array.from(['c', 'd'].entries()).join(';')"));
  133. Assert.Equal("0,e;1,f", _engine.Evaluate("Array.from([[0, 'e'],[1, 'f']]).join(';')"));
  134. }
  135. [Fact]
  136. public void ArrayEntriesShouldReturnKeyValuePairs()
  137. {
  138. Assert.Equal("0,hello,1,world", _engine.Evaluate("Array.from(['hello', 'world'].entries()).join()"));
  139. Assert.Equal("0,hello;1,world", _engine.Evaluate("Array.from(['hello', 'world'].entries()).join(';')"));
  140. Assert.Equal("0,;1,1;2,5", _engine.Evaluate("Array.from([,1,5,].entries()).join(';')"));
  141. }
  142. [Fact]
  143. public void IteratorsShouldHaveIteratorSymbol()
  144. {
  145. _engine.Execute("assert(!!['hello'].values()[Symbol.iterator])");
  146. _engine.Execute("assert(!!new Map([['hello', 'world']]).keys()[Symbol.iterator])");
  147. }
  148. [Fact]
  149. public void ArraySortDoesNotCrashInDebugMode()
  150. {
  151. var engine = new Engine(o =>
  152. {
  153. o.DebugMode(true);
  154. });
  155. engine.SetValue("equal", new Action<object, object>(Assert.Equal));
  156. const string code = @"
  157. var items = [5,2,4,1];
  158. items.sort((a,b) => a - b);
  159. equal('1,2,4,5', items.join());
  160. ";
  161. engine.Execute(code);
  162. }
  163. }
  164. }