ModuleNamespace.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 bool PreventExtensions() => 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. // https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-get-p-receiver
  73. public override JsValue Get(JsValue property, JsValue receiver)
  74. {
  75. if (property.IsSymbol())
  76. {
  77. return base.Get(property, receiver);
  78. }
  79. var p = TypeConverter.ToString(property);
  80. if (!_exports.Contains(p))
  81. {
  82. return Undefined;
  83. }
  84. var m = _module;
  85. var binding = m.ResolveExport(p);
  86. var targetModule = binding.Module;
  87. if (binding.BindingName == "*namespace*")
  88. {
  89. return JsModule.GetModuleNamespace(targetModule);
  90. }
  91. var targetEnv = targetModule._environment;
  92. if (targetEnv is null)
  93. {
  94. ExceptionHelper.ThrowReferenceError(_engine.Realm, "environment");
  95. }
  96. return targetEnv.GetBindingValue(binding.BindingName, true);
  97. }
  98. public override bool Set(JsValue property, JsValue value, JsValue receiver)
  99. {
  100. return false;
  101. }
  102. public override bool Delete(JsValue property)
  103. {
  104. if (property.IsSymbol())
  105. {
  106. return base.Delete(property);
  107. }
  108. var p = TypeConverter.ToString(property);
  109. return !_exports.Contains(p);
  110. }
  111. public override List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
  112. {
  113. var keys = base.GetOwnPropertyKeys(types);
  114. if ((types & Types.String) != 0)
  115. {
  116. foreach (var export in _exports)
  117. {
  118. keys.Add(export);
  119. }
  120. }
  121. return keys;
  122. }
  123. }