PublicInterfaceTests.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System.Collections.Concurrent;
  2. using Jint.Native;
  3. using Jint.Native.Function;
  4. namespace Jint.Tests.PublicInterface;
  5. public class PublicInterfaceTests
  6. {
  7. [Fact]
  8. public void CanCallEval()
  9. {
  10. var engine = new Engine();
  11. var value = engine.Intrinsics.Eval.Call("1 + 1");
  12. Assert.Equal(2, value);
  13. }
  14. [Fact]
  15. public void BindFunctionInstancesArePublic()
  16. {
  17. var engine = new Engine(options =>
  18. {
  19. options.AllowClr();
  20. });
  21. using var emulator = new SetTimeoutEmulator(engine);
  22. engine.SetValue("emulator", emulator);
  23. engine.Execute(@"
  24. var coolingObject = {
  25. coolDownTime: 1000,
  26. cooledDown: false
  27. }
  28. emulator.SetTimeout(function() {
  29. coolingObject.cooledDown = true;
  30. }.bind(coolingObject), coolingObject.coolDownTime);
  31. ");
  32. }
  33. [Fact]
  34. public void JsArgumentsIsPublic()
  35. {
  36. // debuggers might want to access the information
  37. var obj = new Engine().Execute("function f() { return arguments; }").Evaluate("f('a', 'b', 'c');");
  38. var arguments = Assert.IsType<JsArguments>(obj);
  39. Assert.Equal((uint) 3, arguments.Length);
  40. }
  41. private sealed class SetTimeoutEmulator : IDisposable
  42. {
  43. private readonly Engine _engine;
  44. private readonly ConcurrentQueue<JsValue> _queue = new();
  45. private readonly Task _queueProcessor;
  46. private readonly CancellationTokenSource _quit = new();
  47. private bool _disposedValue;
  48. public SetTimeoutEmulator(Engine engine)
  49. {
  50. _engine = engine ?? throw new ArgumentNullException(nameof(engine));
  51. _queueProcessor = Task.Run(() =>
  52. {
  53. while (!_quit.IsCancellationRequested)
  54. {
  55. while (_queue.TryDequeue(out var queueEntry))
  56. {
  57. lock (_engine)
  58. {
  59. if (queueEntry is Function fi)
  60. {
  61. _engine.Invoke(fi);
  62. }
  63. else if (queueEntry is BindFunction bfi)
  64. {
  65. _engine.Invoke(bfi);
  66. }
  67. else
  68. {
  69. _engine.Execute(queueEntry.ToString());
  70. }
  71. }
  72. }
  73. }
  74. });
  75. }
  76. public void SetTimeout(JsValue script, object timeout)
  77. {
  78. _queue.Enqueue(script);
  79. }
  80. private void Dispose(bool disposing)
  81. {
  82. if (!_disposedValue)
  83. {
  84. if (disposing)
  85. {
  86. // TODO: dispose managed state (managed objects)
  87. _quit.Cancel();
  88. _queueProcessor.Wait();
  89. }
  90. _disposedValue = true;
  91. }
  92. }
  93. public void Dispose()
  94. {
  95. // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
  96. Dispose(disposing: true);
  97. GC.SuppressFinalize(this);
  98. }
  99. }
  100. }