2
0

Host.cs 6.6 KB

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