JavaScriptException.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #nullable enable
  2. using System;
  3. using Esprima;
  4. using Jint.Native;
  5. using Jint.Native.Error;
  6. using Jint.Native.Object;
  7. using Jint.Pooling;
  8. namespace Jint.Runtime
  9. {
  10. public class JavaScriptException : JintException
  11. {
  12. private string? _callStack;
  13. public JavaScriptException(ErrorConstructor errorConstructor) : base("")
  14. {
  15. Error = errorConstructor.Construct(Arguments.Empty);
  16. }
  17. public JavaScriptException(ErrorConstructor errorConstructor, string? message, Exception? innerException)
  18. : base(message, innerException)
  19. {
  20. Error = errorConstructor.Construct(new JsValue[] { message });
  21. }
  22. public JavaScriptException(ErrorConstructor errorConstructor, string? message)
  23. : base(message)
  24. {
  25. Error = errorConstructor.Construct(new JsValue[] { message });
  26. }
  27. public JavaScriptException(JsValue error)
  28. {
  29. Error = error;
  30. }
  31. internal JavaScriptException SetCallstack(Engine engine, Location location)
  32. {
  33. Location = location;
  34. var value = engine.CallStack.BuildCallStackString(location);
  35. _callStack = value;
  36. if (Error.IsObject())
  37. {
  38. Error.AsObject()
  39. .FastAddProperty(CommonProperties.Stack, new JsString(value), false, false, false);
  40. }
  41. return this;
  42. }
  43. private string? GetErrorMessage()
  44. {
  45. if (Error is ObjectInstance oi)
  46. {
  47. return oi.Get(CommonProperties.Message).ToString();
  48. }
  49. return null;
  50. }
  51. public JsValue Error { get; }
  52. public override string Message => GetErrorMessage() ?? TypeConverter.ToString(Error);
  53. /// <summary>
  54. /// Returns the call stack of the exception. Requires that engine was built using
  55. /// <see cref="Options.CollectStackTrace"/>.
  56. /// </summary>
  57. public override string? StackTrace
  58. {
  59. get
  60. {
  61. if (_callStack is not null)
  62. {
  63. return _callStack;
  64. }
  65. if (Error is not ObjectInstance oi)
  66. {
  67. return null;
  68. }
  69. var callstack = oi.Get(CommonProperties.Stack, Error);
  70. return callstack.IsUndefined()
  71. ? null
  72. : callstack.AsString();
  73. }
  74. }
  75. public Location Location { get; private set; }
  76. public int LineNumber => Location.Start.Line;
  77. public int Column => Location.Start.Column;
  78. public override string ToString()
  79. {
  80. // adapted custom version as logic differs between full framework and .NET Core
  81. var className = GetType().ToString();
  82. var message = Message;
  83. var innerExceptionString = InnerException?.ToString() ?? "";
  84. const string endOfInnerExceptionResource = "--- End of inner exception stack trace ---";
  85. var stackTrace = StackTrace;
  86. using var rent = StringBuilderPool.Rent();
  87. var sb = rent.Builder;
  88. sb.Append(className);
  89. if (!string.IsNullOrEmpty(message))
  90. {
  91. sb.Append(": ");
  92. sb.Append(message);
  93. }
  94. if (InnerException != null)
  95. {
  96. sb.Append(Environment.NewLine);
  97. sb.Append(" ---> ");
  98. sb.Append(innerExceptionString);
  99. sb.Append(Environment.NewLine);
  100. sb.Append(" ");
  101. sb.Append(endOfInnerExceptionResource);
  102. }
  103. if (stackTrace != null)
  104. {
  105. sb.Append(Environment.NewLine);
  106. sb.Append(stackTrace);
  107. }
  108. return rent.ToString();
  109. }
  110. }
  111. }