JavaScriptException.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 SetLocation(Location location)
  32. {
  33. Location = location;
  34. return this;
  35. }
  36. internal JavaScriptException SetCallstack(Engine engine, Location location)
  37. {
  38. Location = location;
  39. var value = engine.CallStack.BuildCallStackString(location);
  40. _callStack = value;
  41. if (Error.IsObject())
  42. {
  43. Error.AsObject()
  44. .FastAddProperty(CommonProperties.Stack, new JsString(value), false, false, false);
  45. }
  46. return this;
  47. }
  48. private string? GetErrorMessage()
  49. {
  50. if (Error is ObjectInstance oi)
  51. {
  52. return oi.Get(CommonProperties.Message).ToString();
  53. }
  54. return null;
  55. }
  56. public JsValue Error { get; }
  57. public override string Message => GetErrorMessage() ?? TypeConverter.ToString(Error);
  58. /// <summary>
  59. /// Returns the call stack of the exception. Requires that engine was built using
  60. /// <see cref="Options.CollectStackTrace"/>.
  61. /// </summary>
  62. public override string? StackTrace
  63. {
  64. get
  65. {
  66. if (_callStack is not null)
  67. {
  68. return _callStack;
  69. }
  70. if (Error is not ObjectInstance oi)
  71. {
  72. return null;
  73. }
  74. var callstack = oi.Get(CommonProperties.Stack, Error);
  75. return callstack.IsUndefined()
  76. ? null
  77. : callstack.AsString();
  78. }
  79. }
  80. public Location Location { get; private set; }
  81. public int LineNumber => Location.Start.Line;
  82. public int Column => Location.Start.Column;
  83. public override string ToString()
  84. {
  85. // adapted custom version as logic differs between full framework and .NET Core
  86. var className = GetType().ToString();
  87. var message = Message;
  88. var innerExceptionString = InnerException?.ToString() ?? "";
  89. const string endOfInnerExceptionResource = "--- End of inner exception stack trace ---";
  90. var stackTrace = StackTrace;
  91. using var rent = StringBuilderPool.Rent();
  92. var sb = rent.Builder;
  93. sb.Append(className);
  94. if (!string.IsNullOrEmpty(message))
  95. {
  96. sb.Append(": ");
  97. sb.Append(message);
  98. }
  99. if (InnerException != null)
  100. {
  101. sb.Append(Environment.NewLine);
  102. sb.Append(" ---> ");
  103. sb.Append(innerExceptionString);
  104. sb.Append(Environment.NewLine);
  105. sb.Append(" ");
  106. sb.Append(endOfInnerExceptionResource);
  107. }
  108. if (stackTrace != null)
  109. {
  110. sb.Append(Environment.NewLine);
  111. sb.Append(stackTrace);
  112. }
  113. return rent.ToString();
  114. }
  115. }
  116. }