Options.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Reflection;
  6. using Jint.Native;
  7. using Jint.Native.Object;
  8. using Jint.Runtime.Interop;
  9. using Jint.Runtime.References;
  10. namespace Jint
  11. {
  12. public delegate JsValue MemberAccessorDelegate(Engine engine, object target, string member);
  13. public sealed class Options
  14. {
  15. private readonly List<IConstraint> _constraints = new List<IConstraint>();
  16. private bool _strict;
  17. private bool _allowDebuggerStatement;
  18. private bool _allowClr;
  19. private bool _allowClrWrite = true;
  20. private readonly List<IObjectConverter> _objectConverters = new List<IObjectConverter>();
  21. private Func<Engine, object, ObjectInstance> _wrapObjectHandler;
  22. private MemberAccessorDelegate _memberAccessor;
  23. private int _maxRecursionDepth = -1;
  24. private TimeSpan _regexTimeoutInterval = TimeSpan.FromSeconds(10);
  25. private CultureInfo _culture = CultureInfo.CurrentCulture;
  26. private TimeZoneInfo _localTimeZone = TimeZoneInfo.Local;
  27. private List<Assembly> _lookupAssemblies = new List<Assembly>();
  28. private Predicate<Exception> _clrExceptionsHandler;
  29. private IReferenceResolver _referenceResolver = DefaultReferenceResolver.Instance;
  30. private readonly List<Action<Engine>> _configurations = new List<Action<Engine>>();
  31. /// <summary>
  32. /// Run the script in strict mode.
  33. /// </summary>
  34. public Options Strict(bool strict = true)
  35. {
  36. _strict = strict;
  37. return this;
  38. }
  39. /// <summary>
  40. /// Allow the <code>debugger</code> statement to be called in a script.
  41. /// </summary>
  42. /// <remarks>
  43. /// Because the <code>debugger</code> statement can start the
  44. /// Visual Studio debugger, is it disabled by default
  45. /// </remarks>
  46. public Options AllowDebuggerStatement(bool allowDebuggerStatement = true)
  47. {
  48. _allowDebuggerStatement = allowDebuggerStatement;
  49. return this;
  50. }
  51. /// <summary>
  52. /// Allow to run the script in debug mode.
  53. /// </summary>
  54. public Options DebugMode(bool debugMode = true)
  55. {
  56. IsDebugMode = debugMode;
  57. return this;
  58. }
  59. /// <summary>
  60. /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
  61. /// </summary>
  62. public Options AddObjectConverter<T>() where T : IObjectConverter, new()
  63. {
  64. return AddObjectConverter(new T());
  65. }
  66. /// <summary>
  67. /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
  68. /// </summary>
  69. public Options AddObjectConverter(IObjectConverter objectConverter)
  70. {
  71. _objectConverters.Add(objectConverter);
  72. return this;
  73. }
  74. /// <summary>
  75. /// If no known type could be guessed, objects are normally wrapped as an
  76. /// ObjectInstance using class ObjectWrapper. This function can be used to
  77. /// register a handler for a customized handling.
  78. /// </summary>
  79. public Options SetWrapObjectHandler(Func<Engine, object, ObjectInstance> wrapObjectHandler)
  80. {
  81. _wrapObjectHandler = wrapObjectHandler;
  82. return this;
  83. }
  84. /// <summary>
  85. /// Sets the type converter to use.
  86. /// </summary>
  87. public Options SetTypeConverter(Func<Engine, ITypeConverter> typeConverterFactory)
  88. {
  89. _configurations.Add(engine => engine.ClrTypeConverter = typeConverterFactory(engine));
  90. return this;
  91. }
  92. /// <summary>
  93. /// Registers a delegate that is called when CLR members are invoked. This allows
  94. /// to change what values are returned for specific CLR objects, or if any value
  95. /// is returned at all.
  96. /// </summary>
  97. /// <param name="accessor">
  98. /// The delegate to invoke for each CLR member. If the delegate
  99. /// returns <c>null</c>, the standard evaluation is performed.
  100. /// </param>
  101. public Options SetMemberAccessor(MemberAccessorDelegate accessor)
  102. {
  103. _memberAccessor = accessor;
  104. return this;
  105. }
  106. /// <summary>
  107. /// Allows scripts to call CLR types directly like <example>System.IO.File</example>
  108. /// </summary>
  109. public Options AllowClr(params Assembly[] assemblies)
  110. {
  111. _allowClr = true;
  112. _lookupAssemblies.AddRange(assemblies);
  113. _lookupAssemblies = _lookupAssemblies.Distinct().ToList();
  114. return this;
  115. }
  116. public Options AllowClrWrite(bool allow = true)
  117. {
  118. _allowClrWrite = allow;
  119. return this;
  120. }
  121. /// <summary>
  122. /// Exceptions thrown from CLR code are converted to JavaScript errors and
  123. /// can be used in at try/catch statement. By default these exceptions are bubbled
  124. /// to the CLR host and interrupt the script execution.
  125. /// </summary>
  126. public Options CatchClrExceptions()
  127. {
  128. CatchClrExceptions(_ => true);
  129. return this;
  130. }
  131. /// <summary>
  132. /// Exceptions that thrown from CLR code are converted to JavaScript errors and
  133. /// can be used in at try/catch statement. By default these exceptions are bubbled
  134. /// to the CLR host and interrupt the script execution.
  135. /// </summary>
  136. public Options CatchClrExceptions(Predicate<Exception> handler)
  137. {
  138. _clrExceptionsHandler = handler;
  139. return this;
  140. }
  141. public Options Constraint(IConstraint constraint)
  142. {
  143. if (constraint != null)
  144. {
  145. _constraints.Add(constraint);
  146. }
  147. return this;
  148. }
  149. public Options WithoutConstraint(Predicate<IConstraint> predicate)
  150. {
  151. _constraints.RemoveAll(predicate);
  152. return this;
  153. }
  154. public Options RegexTimeoutInterval(TimeSpan regexTimeoutInterval)
  155. {
  156. _regexTimeoutInterval = regexTimeoutInterval;
  157. return this;
  158. }
  159. /// <summary>
  160. /// Sets maximum allowed depth of recursion.
  161. /// </summary>
  162. /// <param name="maxRecursionDepth">
  163. /// The allowed depth.
  164. /// a) In case max depth is zero no recursion is allowed.
  165. /// b) In case max depth is equal to n it means that in one scope function can be called no more than n times.
  166. /// </param>
  167. /// <returns>Options instance for fluent syntax</returns>
  168. public Options LimitRecursion(int maxRecursionDepth = 0)
  169. {
  170. _maxRecursionDepth = maxRecursionDepth;
  171. return this;
  172. }
  173. public Options Culture(CultureInfo cultureInfo)
  174. {
  175. _culture = cultureInfo;
  176. return this;
  177. }
  178. public Options LocalTimeZone(TimeZoneInfo timeZoneInfo)
  179. {
  180. _localTimeZone = timeZoneInfo;
  181. return this;
  182. }
  183. public Options SetReferencesResolver(IReferenceResolver resolver)
  184. {
  185. _referenceResolver = resolver;
  186. return this;
  187. }
  188. /// <summary>
  189. /// Registers some custom logic to apply on an <see cref="Engine"/> instance when the options
  190. /// are loaded.
  191. /// </summary>
  192. /// <param name="configuration">The action to register.</param>
  193. public Options Configure(Action<Engine> configuration)
  194. {
  195. _configurations.Add(configuration);
  196. return this;
  197. }
  198. /// <summary>
  199. /// Called by the <see cref="Engine"/> instance that loads this <see cref="Options" />
  200. /// once it is loaded.
  201. /// </summary>
  202. internal void Apply(Engine engine)
  203. {
  204. foreach (var configuration in _configurations)
  205. {
  206. configuration?.Invoke(engine);
  207. }
  208. }
  209. internal bool IsStrict => _strict;
  210. internal bool _IsDebuggerStatementAllowed => _allowDebuggerStatement;
  211. internal bool IsDebugMode { get; private set; }
  212. internal bool _IsClrAllowed => _allowClr;
  213. internal bool _IsClrWriteAllowed => _allowClrWrite;
  214. internal Predicate<Exception> _ClrExceptionsHandler => _clrExceptionsHandler;
  215. internal List<Assembly> _LookupAssemblies => _lookupAssemblies;
  216. internal List<IObjectConverter> _ObjectConverters => _objectConverters;
  217. internal List<IConstraint> _Constraints => _constraints;
  218. internal Func<Engine, object, ObjectInstance> _WrapObjectHandler => _wrapObjectHandler;
  219. internal MemberAccessorDelegate _MemberAccessor => _memberAccessor;
  220. internal int MaxRecursionDepth => _maxRecursionDepth;
  221. internal TimeSpan _RegexTimeoutInterval => _regexTimeoutInterval;
  222. internal CultureInfo _Culture => _culture;
  223. internal TimeZoneInfo _LocalTimeZone => _localTimeZone;
  224. internal IReferenceResolver ReferenceResolver => _referenceResolver;
  225. private sealed class DefaultReferenceResolver : IReferenceResolver
  226. {
  227. public static readonly DefaultReferenceResolver Instance = new DefaultReferenceResolver();
  228. private DefaultReferenceResolver()
  229. {
  230. }
  231. public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
  232. {
  233. value = JsValue.Undefined;
  234. return false;
  235. }
  236. public bool TryPropertyReference(Engine engine, Reference reference, ref JsValue value)
  237. {
  238. return false;
  239. }
  240. public bool TryGetCallable(Engine engine, object callee, out JsValue value)
  241. {
  242. value = JsValue.Undefined;
  243. return false;
  244. }
  245. public bool CheckCoercible(JsValue value)
  246. {
  247. return false;
  248. }
  249. }
  250. }
  251. }