ShadowRealmTests.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using Jint.Native.Object;
  2. namespace Jint.Tests.PublicInterface;
  3. public class ShadowRealmTests
  4. {
  5. [Fact]
  6. public void CanUseViaEngineMethods()
  7. {
  8. var engine = new Engine(options => options.EnableModules(GetBasePath()));
  9. var shadowRealm = engine.Intrinsics.ShadowRealm.Construct();
  10. // lexically scoped (let/const) are visible during single call
  11. Assert.Equal(123, shadowRealm.Evaluate("const s = 123; const f = () => s; f();"));
  12. Assert.Equal(true, shadowRealm.Evaluate("typeof f === 'undefined'"));
  13. // vars hold longer
  14. Assert.Equal(456, shadowRealm.Evaluate("function foo() { return 456; }; foo();"));
  15. Assert.Equal(456, shadowRealm.Evaluate("foo();"));
  16. // not visible in global engine though
  17. Assert.Equal(true, engine.Evaluate("typeof foo === 'undefined'"));
  18. // modules
  19. var importValue = shadowRealm.ImportValue("./modules/format-name.js", "formatName");
  20. var formatName = (ObjectInstance) importValue.UnwrapIfPromise();
  21. var result = engine.Invoke(formatName, "John", "Doe").AsString();
  22. Assert.Equal("John Doe", result);
  23. }
  24. [Fact]
  25. public void MultipleShadowRealmsDoNotInterfere()
  26. {
  27. var engine = new Engine(options => options.EnableModules(GetBasePath()));
  28. engine.SetValue("message", "world");
  29. engine.Evaluate("function hello() {return message}");
  30. Assert.Equal("world", engine.Evaluate("hello();"));
  31. var shadowRealm = engine.Intrinsics.ShadowRealm.Construct();
  32. shadowRealm.SetValue("message", "realm 1");
  33. shadowRealm.Evaluate("function hello() {return message}");
  34. var shadowRealm2 = engine.Intrinsics.ShadowRealm.Construct();
  35. shadowRealm2.SetValue("message", "realm 2");
  36. shadowRealm2.Evaluate("function hello() {return message}");
  37. // Act & Assert
  38. Assert.Equal("realm 1", shadowRealm.Evaluate("hello();"));
  39. Assert.Equal("realm 2", shadowRealm2.Evaluate("hello();"));
  40. }
  41. [Fact]
  42. public void MultipleShadowRealm_SettingGlobalVariable_DoNotInterfere()
  43. {
  44. var engine = new Engine(options => options.EnableModules(GetBasePath()));
  45. engine.SetValue("message", "hello ");
  46. engine.Evaluate("(function hello() {message += \"engine\"})();");
  47. var shadowRealm = engine.Intrinsics.ShadowRealm.Construct();
  48. shadowRealm.SetValue("message", "hello ");
  49. shadowRealm.Evaluate("(function hello() {message += \"realm 1\"})();");
  50. var shadowRealm2 = engine.Intrinsics.ShadowRealm.Construct();
  51. shadowRealm2.SetValue("message", "hello ");
  52. shadowRealm2.Evaluate("(function hello() {message += \"realm 2\"})();");
  53. // Act & Assert
  54. Assert.Equal("hello engine", engine.Evaluate("message"));
  55. Assert.Equal("hello realm 1", shadowRealm.Evaluate("message"));
  56. Assert.Equal("hello realm 2", shadowRealm2.Evaluate("message"));
  57. }
  58. [Fact]
  59. public void CanReuseScriptWithShadowRealm()
  60. {
  61. var engine = new Engine(options => options.EnableModules(GetBasePath()));
  62. engine.SetValue("message", "engine");
  63. var shadowRealm = engine.Intrinsics.ShadowRealm.Construct();
  64. shadowRealm.SetValue("message", "realm 1");
  65. var shadowRealm2 = engine.Intrinsics.ShadowRealm.Construct();
  66. shadowRealm2.SetValue("message", "realm 2");
  67. var script = Engine.PrepareScript("(function hello() {return \"hello \" + message})();");
  68. // Act & Assert
  69. Assert.Equal("hello engine", engine.Evaluate(script));
  70. Assert.Equal("hello realm 1", shadowRealm.Evaluate(script));
  71. Assert.Equal("hello realm 2", shadowRealm2.Evaluate(script));
  72. }
  73. private static string GetBasePath()
  74. {
  75. var assemblyDirectory = new DirectoryInfo(AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory);
  76. var current = assemblyDirectory;
  77. var binDirectory = $"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}";
  78. while (current is not null)
  79. {
  80. if (current.FullName.Contains(binDirectory) || current.Name == "bin")
  81. {
  82. current = current.Parent;
  83. continue;
  84. }
  85. var testDirectory = current.GetDirectories("Jint.Tests").FirstOrDefault();
  86. if (testDirectory == null)
  87. {
  88. current = current.Parent;
  89. continue;
  90. }
  91. // found it
  92. current = testDirectory;
  93. break;
  94. }
  95. if (current is null)
  96. {
  97. throw new NullReferenceException($"Could not find tests base path, assemblyPath: {assemblyDirectory}");
  98. }
  99. return Path.Combine(current.FullName, "Runtime", "Scripts");
  100. }
  101. }