jserror.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "jsi.h"
  2. #define QQ(X) #X
  3. #define Q(X) QQ(X)
  4. static int jsB_stacktrace(js_State *J, int skip)
  5. {
  6. char buf[256];
  7. int n = J->tracetop - skip;
  8. if (n <= 0)
  9. return 0;
  10. for (; n > 0; --n) {
  11. const char *name = J->trace[n].name;
  12. const char *file = J->trace[n].file;
  13. int line = J->trace[n].line;
  14. if (line > 0) {
  15. if (name[0])
  16. snprintf(buf, sizeof buf, "\n\tat %s (%s:%d)", name, file, line);
  17. else
  18. snprintf(buf, sizeof buf, "\n\tat %s:%d", file, line);
  19. } else
  20. snprintf(buf, sizeof buf, "\n\tat %s (%s)", name, file);
  21. js_pushstring(J, buf);
  22. if (n < J->tracetop - skip)
  23. js_concat(J);
  24. }
  25. return 1;
  26. }
  27. static void Ep_toString(js_State *J)
  28. {
  29. const char *name = "Error";
  30. const char *message = "";
  31. if (!js_isobject(J, -1))
  32. js_typeerror(J, "not an object");
  33. if (js_hasproperty(J, 0, "name"))
  34. name = js_tostring(J, -1);
  35. if (js_hasproperty(J, 0, "message"))
  36. message = js_tostring(J, -1);
  37. if (name[0] == 0)
  38. js_pushstring(J, message);
  39. else if (message[0] == 0)
  40. js_pushstring(J, name);
  41. else {
  42. js_pushstring(J, name);
  43. js_pushstring(J, ": ");
  44. js_concat(J);
  45. js_pushstring(J, message);
  46. js_concat(J);
  47. }
  48. }
  49. static int jsB_ErrorX(js_State *J, js_Object *prototype)
  50. {
  51. js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
  52. if (js_isdefined(J, 1)) {
  53. js_pushstring(J, js_tostring(J, 1));
  54. js_defproperty(J, -2, "message", JS_DONTENUM);
  55. }
  56. if (jsB_stacktrace(J, 1))
  57. js_defproperty(J, -2, "stackTrace", JS_DONTENUM);
  58. return 1;
  59. }
  60. static void js_newerrorx(js_State *J, const char *message, js_Object *prototype)
  61. {
  62. js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
  63. js_pushstring(J, message);
  64. js_setproperty(J, -2, "message");
  65. if (jsB_stacktrace(J, 0))
  66. js_setproperty(J, -2, "stackTrace");
  67. }
  68. #define DERROR(name, Name) \
  69. static void jsB_##Name(js_State *J) { \
  70. jsB_ErrorX(J, J->Name##_prototype); \
  71. } \
  72. void js_new##name(js_State *J, const char *s) { \
  73. js_newerrorx(J, s, J->Name##_prototype); \
  74. } \
  75. void js_##name(js_State *J, const char *fmt, ...) { \
  76. va_list ap; \
  77. char buf[256]; \
  78. va_start(ap, fmt); \
  79. vsnprintf(buf, sizeof buf, fmt, ap); \
  80. va_end(ap); \
  81. js_newerrorx(J, buf, J->Name##_prototype); \
  82. js_throw(J); \
  83. }
  84. DERROR(error, Error)
  85. DERROR(evalerror, EvalError)
  86. DERROR(rangeerror, RangeError)
  87. DERROR(referenceerror, ReferenceError)
  88. DERROR(syntaxerror, SyntaxError)
  89. DERROR(typeerror, TypeError)
  90. DERROR(urierror, URIError)
  91. #undef DERROR
  92. void jsB_initerror(js_State *J)
  93. {
  94. js_pushobject(J, J->Error_prototype);
  95. {
  96. jsB_props(J, "name", "Error");
  97. jsB_propf(J, "Error.prototype.toString", Ep_toString, 0);
  98. }
  99. js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1);
  100. js_defglobal(J, "Error", JS_DONTENUM);
  101. #define IERROR(NAME) \
  102. js_pushobject(J, J->NAME##_prototype); \
  103. jsB_props(J, "name", Q(NAME)); \
  104. js_newcconstructor(J, jsB_##NAME, jsB_##NAME, Q(NAME), 1); \
  105. js_defglobal(J, Q(NAME), JS_DONTENUM);
  106. IERROR(EvalError);
  107. IERROR(RangeError);
  108. IERROR(ReferenceError);
  109. IERROR(SyntaxError);
  110. IERROR(TypeError);
  111. IERROR(URIError);
  112. #undef IERROR
  113. }