ModuleNamespace.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System.Collections.Generic;
  2. using Jint.Native;
  3. using Jint.Native.Object;
  4. using Jint.Runtime.Descriptors;
  5. namespace Jint.Runtime.Modules;
  6. /// <summary>
  7. /// https://tc39.es/ecma262/#sec-module-namespace-exotic-objects
  8. /// </summary>
  9. internal sealed class ModuleNamespace : ObjectInstance
  10. {
  11. private readonly JsModule _module;
  12. private readonly HashSet<string> _exports;
  13. public ModuleNamespace(Engine engine, JsModule module, List<string> exports) : base(engine)
  14. {
  15. _module = module;
  16. exports.Sort();
  17. _exports = new HashSet<string>(exports);
  18. }
  19. protected internal override ObjectInstance GetPrototypeOf() => null;
  20. public override bool SetPrototypeOf(JsValue value) => SetImmutablePrototype(value);
  21. private bool SetImmutablePrototype(JsValue value)
  22. {
  23. var current = GetPrototypeOf();
  24. return SameValue(value, current ?? Null);
  25. }
  26. public override bool Extensible => false;
  27. public override JsValue PreventExtensions() => JsBoolean.True;
  28. public override PropertyDescriptor GetOwnProperty(JsValue property)
  29. {
  30. if (property.IsSymbol())
  31. {
  32. return base.GetOwnProperty(property);
  33. }
  34. var p = TypeConverter.ToString(property);
  35. if (!_exports.Contains(p))
  36. {
  37. return PropertyDescriptor.Undefined;
  38. }
  39. var value = Get(property);
  40. return new PropertyDescriptor(value, true, true, false);
  41. }
  42. public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
  43. {
  44. if (property.IsSymbol())
  45. {
  46. return base.DefineOwnProperty(property, desc);
  47. }
  48. var current = GetOwnProperty(property);
  49. if (current == PropertyDescriptor.Undefined)
  50. {
  51. return false;
  52. }
  53. if (desc.Configurable || desc.Enumerable || desc.IsAccessorDescriptor() || !desc.Writable)
  54. {
  55. return false;
  56. }
  57. if (desc.Value is not null)
  58. {
  59. return SameValue(desc.Value, current.Value);
  60. }
  61. return true;
  62. }
  63. public override bool HasProperty(JsValue property)
  64. {
  65. if (property.IsSymbol())
  66. {
  67. return base.HasProperty(property);
  68. }
  69. var p = TypeConverter.ToString(property);
  70. return _exports.Contains(p);
  71. }
  72. public override JsValue Get(JsValue property, JsValue receiver)
  73. {
  74. if (property.IsSymbol())
  75. {
  76. return base.Get(property, receiver);
  77. }
  78. var p = TypeConverter.ToString(property);
  79. if (!_exports.Contains(p))
  80. {
  81. return Undefined;
  82. }
  83. var m = _module;
  84. var binding = m.ResolveExport(p);
  85. var targetModule = binding.Module;
  86. if (binding.BindingName == "*namespace*")
  87. {
  88. return JsModule.GetModuleNamespace(targetModule);
  89. }
  90. var targetEnv = targetModule._environment;
  91. if (targetEnv is null)
  92. {
  93. ExceptionHelper.ThrowReferenceError(_engine.Realm, "environment");
  94. }
  95. return targetEnv.GetBindingValue(binding.BindingName, true);
  96. }
  97. public override bool Set(JsValue property, JsValue value, JsValue receiver)
  98. {
  99. return false;
  100. }
  101. public override bool Delete(JsValue property)
  102. {
  103. if (property.IsSymbol())
  104. {
  105. return base.Delete(property);
  106. }
  107. var p = TypeConverter.ToString(property);
  108. return !_exports.Contains(p);
  109. }
  110. public override List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
  111. {
  112. var keys = base.GetOwnPropertyKeys(types);
  113. if ((types & Types.String) != 0)
  114. {
  115. foreach (var export in _exports)
  116. {
  117. keys.Add(export);
  118. }
  119. }
  120. return keys;
  121. }
  122. }