NullPropagation.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. using Jint.Native;
  2. using Jint.Native.Object;
  3. using Jint.Parser;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Interop;
  6. using Jint.Runtime.References;
  7. using Xunit;
  8. namespace Jint.Tests.Runtime
  9. {
  10. public class NullPropagation
  11. {
  12. public class NullPropagationReferenceResolver : IReferenceResolver
  13. {
  14. public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
  15. {
  16. value = reference.GetBase();
  17. return true;
  18. }
  19. public bool TryPropertyReference(Engine engine, Reference reference, ref JsValue value)
  20. {
  21. return value.IsNull() || value.IsUndefined();
  22. }
  23. public bool TryGetCallable(Engine engine, object reference, out JsValue value)
  24. {
  25. value = new JsValue(
  26. new ClrFunctionInstance(engine, (thisObj, values) => thisObj)
  27. );
  28. return true;
  29. }
  30. public bool CheckCoercible(JsValue value)
  31. {
  32. return true;
  33. }
  34. }
  35. [Fact]
  36. public void NullPropagationTest()
  37. {
  38. var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
  39. const string Script = @"
  40. var input = {
  41. Address : null
  42. };
  43. var address = input.Address;
  44. var city = input.Address.City;
  45. var length = input.Address.City.length;
  46. var output = {
  47. Count1 : input.Address.City.length,
  48. Count2 : this.XYZ.length
  49. };
  50. ";
  51. engine.Execute(Script);
  52. var address = engine.GetValue("address");
  53. var city = engine.GetValue("city");
  54. var length = engine.GetValue("length");
  55. var output = engine.GetValue("output").AsObject();
  56. Assert.Equal(Null.Instance, address);
  57. Assert.Equal(Null.Instance, city);
  58. Assert.Equal(Null.Instance, length);
  59. Assert.Equal(Null.Instance, output.Get("Count1"));
  60. Assert.Equal(Undefined.Instance, output.Get("Count2"));
  61. }
  62. [Fact]
  63. public void NullPropagationFromArg()
  64. {
  65. var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
  66. const string Script = @"
  67. function test(arg) {
  68. return arg.Name;
  69. }
  70. function test2(arg) {
  71. return arg.Name.toUpperCase();
  72. }
  73. ";
  74. engine.Execute(Script);
  75. var result = engine.Invoke("test", Null.Instance);
  76. Assert.Equal(Null.Instance, result);
  77. result = engine.Invoke("test2", Null.Instance);
  78. Assert.Equal(Null.Instance, result);
  79. }
  80. [Fact]
  81. public void NullPropagationShouldNotAffectOperators()
  82. {
  83. var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
  84. var jsObject = engine.Object.Construct(Arguments.Empty);
  85. jsObject.Put("NullField", JsValue.Null, true);
  86. var script = @"
  87. this.is_nullfield_not_null = this.NullField !== null;
  88. this.is_notnullfield_not_null = this.NotNullField !== null;
  89. this.has_emptyfield_not_null = this.EmptyField !== null;
  90. ";
  91. var wrapperScript = string.Format(@"function ExecutePatchScript(docInner){{ (function(doc){{ {0} }}).apply(docInner); }};", script);
  92. engine.Execute(wrapperScript, new ParserOptions
  93. {
  94. Source = "main.js"
  95. });
  96. engine.Invoke("ExecutePatchScript", jsObject);
  97. Assert.False(jsObject.Get("is_nullfield_not_null").AsBoolean());
  98. Assert.True(jsObject.Get("is_notnullfield_not_null").AsBoolean());
  99. Assert.True(jsObject.Get("has_emptyfield_not_null").AsBoolean());
  100. }
  101. }
  102. }