Host.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #nullable enable
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Jint.Native;
  5. using Jint.Native.Global;
  6. using Jint.Native.Object;
  7. using Jint.Native.Promise;
  8. using Jint.Runtime.Descriptors;
  9. using Jint.Runtime.Environments;
  10. using Jint.Runtime.Interop;
  11. using Jint.Runtime.Modules;
  12. namespace Jint.Runtime
  13. {
  14. public class Host
  15. {
  16. private Engine? _engine;
  17. protected Engine Engine
  18. {
  19. get
  20. {
  21. if (_engine is null)
  22. {
  23. ExceptionHelper.ThrowInvalidOperationException("Initialize has not been called");
  24. }
  25. return _engine!;
  26. }
  27. private set => _engine = value;
  28. }
  29. /// <summary>
  30. /// Initializes the host.
  31. /// </summary>
  32. public void Initialize(Engine engine)
  33. {
  34. Engine = engine;
  35. InitializeHostDefinedRealm();
  36. PostInitialize();
  37. }
  38. protected virtual void PostInitialize()
  39. {
  40. }
  41. /// <summary>
  42. /// https://tc39.es/ecma262/#sec-initializehostdefinedrealm
  43. /// </summary>
  44. protected virtual void InitializeHostDefinedRealm()
  45. {
  46. var realm = CreateRealm();
  47. var newContext = new ExecutionContext(
  48. scriptOrModule: null,
  49. lexicalEnvironment: realm.GlobalEnv,
  50. variableEnvironment: realm.GlobalEnv,
  51. privateEnvironment: null,
  52. realm: realm,
  53. function: null);
  54. Engine.EnterExecutionContext(newContext);
  55. }
  56. protected virtual GlobalEnvironmentRecord CreateGlobalEnvironment(ObjectInstance globalObject)
  57. {
  58. return JintEnvironment.NewGlobalEnvironment(Engine, globalObject, globalObject);
  59. }
  60. protected virtual ObjectInstance CreateGlobalObject(Realm realm)
  61. {
  62. var globalObject = new GlobalObject(Engine, realm);
  63. // Because the properties might need some of the built-in object
  64. // their configuration is delayed to a later step
  65. // trigger initialization
  66. globalObject.EnsureInitialized();
  67. return globalObject;
  68. }
  69. /// <summary>
  70. /// https://tc39.es/ecma262/#sec-createrealm
  71. /// </summary>
  72. protected internal virtual Realm CreateRealm()
  73. {
  74. var realmRec = new Realm();
  75. Engine._realmInConstruction = realmRec;
  76. CreateIntrinsics(realmRec);
  77. var globalObject = CreateGlobalObject(realmRec);
  78. var globalEnv = CreateGlobalEnvironment(globalObject);
  79. realmRec.GlobalEnv = globalEnv;
  80. realmRec.GlobalObject = globalObject;
  81. Engine._realmInConstruction = null;
  82. return realmRec;
  83. }
  84. /// <summary>
  85. /// https://tc39.es/ecma262/#sec-createintrinsics
  86. /// </summary>
  87. protected virtual void CreateIntrinsics(Realm realmRec)
  88. {
  89. var intrinsics = new Intrinsics(Engine, realmRec);
  90. realmRec.Intrinsics = intrinsics;
  91. }
  92. /// <summary>
  93. /// https://tc39.es/ecma262/#sec-hostensurecancompilestrings
  94. /// </summary>
  95. public virtual void EnsureCanCompileStrings(Realm callerRealm, Realm evalRealm)
  96. {
  97. }
  98. /// <summary>
  99. /// https://tc39.es/ecma262/#sec-hostresolveimportedmodule
  100. /// </summary>
  101. internal virtual ModuleRecord ResolveImportedModule(IScriptOrModule? referencingScriptOrModule, string specifier)
  102. {
  103. return Engine.LoadModule(referencingScriptOrModule?.Location, specifier);
  104. }
  105. /// <summary>
  106. /// https://tc39.es/ecma262/#sec-hostimportmoduledynamically
  107. /// </summary>
  108. internal virtual void ImportModuleDynamically(IScriptOrModule? referencingModule, string specifier, PromiseCapability promiseCapability)
  109. {
  110. var promise = Engine.RegisterPromise();
  111. try
  112. {
  113. // This should instead return the PromiseInstance returned by ModuleRecord.Evaluate (currently done in Engine.EvaluateModule), but until we have await this will do.
  114. Engine.ImportModule(specifier, referencingModule?.Location);
  115. promise.Resolve(JsValue.Undefined);
  116. }
  117. catch (JavaScriptException ex)
  118. {
  119. promise.Reject(ex.Error);
  120. }
  121. FinishDynamicImport(referencingModule, specifier, promiseCapability, (PromiseInstance) promise.Promise);
  122. }
  123. /// <summary>
  124. /// https://tc39.es/ecma262/#sec-finishdynamicimport
  125. /// </summary>
  126. internal virtual void FinishDynamicImport(IScriptOrModule? referencingModule, string specifier, PromiseCapability promiseCapability, PromiseInstance innerPromise)
  127. {
  128. var onFulfilled = new ClrFunctionInstance(Engine, "", (thisObj, args) =>
  129. {
  130. var moduleRecord = ResolveImportedModule(referencingModule, specifier);
  131. try
  132. {
  133. var ns = ModuleRecord.GetModuleNamespace(moduleRecord);
  134. promiseCapability.Resolve.Call(JsValue.Undefined, new JsValue[] { ns });
  135. }
  136. catch (JavaScriptException ex)
  137. {
  138. promiseCapability.Reject.Call(JsValue.Undefined, new [] { ex.Error });
  139. }
  140. return JsValue.Undefined;
  141. }, 0, PropertyFlag.Configurable);
  142. var onRejected = new ClrFunctionInstance(Engine, "", (thisObj, args) =>
  143. {
  144. var error = args.At(0);
  145. promiseCapability.Reject.Call(JsValue.Undefined, new [] { error });
  146. return JsValue.Undefined;
  147. }, 0, PropertyFlag.Configurable);
  148. PromiseOperations.PerformPromiseThen(Engine, innerPromise, onFulfilled, onRejected, promiseCapability);
  149. }
  150. /// <summary>
  151. /// https://tc39.es/ecma262/#sec-hostgetimportmetaproperties
  152. /// </summary>
  153. public virtual List<KeyValuePair<JsValue, JsValue>> GetImportMetaProperties(ModuleRecord moduleRecord)
  154. {
  155. return new List<KeyValuePair<JsValue, JsValue>>();
  156. }
  157. /// <summary>
  158. /// https://tc39.es/ecma262/#sec-hostfinalizeimportmeta
  159. /// </summary>
  160. public virtual void FinalizeImportMeta(ObjectInstance importMeta, ModuleRecord moduleRecord)
  161. {
  162. }
  163. /// <summary>
  164. /// https://tc39.es/proposal-shadowrealm/#sec-host-initialize-shadow-shadowrealm
  165. /// </summary>
  166. public virtual void InitializeShadowRealm(Realm realm)
  167. {
  168. }
  169. }
  170. }