Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include "jsi.h"
  2. #include "jsparse.h"
  3. #include "jscompile.h"
  4. #include "jsvalue.h"
  5. #include "jsrun.h"
  6. #include "jsbuiltin.h"
  7.  
  8. #include <assert.h>
  9. #include <errno.h>
  10.  
  11. static void *js_defaultalloc(void *actx, void *ptr, int size)
  12. {
  13. #ifndef __has_feature
  14. #define __has_feature(x) 0
  15. #endif
  16. #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
  17.         if (size == 0) {
  18.                 free(ptr);
  19.                 return NULL;
  20.         }
  21. #endif
  22.         return realloc(ptr, (size_t)size);
  23. }
  24.  
  25. static void js_defaultreport(js_State *J, const char *message)
  26. {
  27.         fputs(message, stderr);
  28.         fputc('\n', stderr);
  29. }
  30.  
  31. static void js_defaultpanic(js_State *J)
  32. {
  33.         js_report(J, "uncaught exception");
  34.         /* return to javascript to abort */
  35. }
  36.  
  37. int js_ploadstring(js_State *J, const char *filename, const char *source)
  38. {
  39.         if (js_try(J))
  40.                 return 1;
  41.         js_loadstring(J, filename, source);
  42.         js_endtry(J);
  43.         return 0;
  44. }
  45.  
  46. int js_ploadfile(js_State *J, const char *filename)
  47. {
  48.         if (js_try(J))
  49.                 return 1;
  50.         js_loadfile(J, filename);
  51.         js_endtry(J);
  52.         return 0;
  53. }
  54.  
  55. const char *js_trystring(js_State *J, int idx, const char *error)
  56. {
  57.         const char *s;
  58.         if (js_try(J)) {
  59.                 js_pop(J, 1);
  60.                 return error;
  61.         }
  62.         s = js_tostring(J, idx);
  63.         js_endtry(J);
  64.         return s;
  65. }
  66.  
  67. double js_trynumber(js_State *J, int idx, double error)
  68. {
  69.         double v;
  70.         if (js_try(J)) {
  71.                 js_pop(J, 1);
  72.                 return error;
  73.         }
  74.         v = js_tonumber(J, idx);
  75.         js_endtry(J);
  76.         return v;
  77. }
  78.  
  79. int js_tryinteger(js_State *J, int idx, int error)
  80. {
  81.         int v;
  82.         if (js_try(J)) {
  83.                 js_pop(J, 1);
  84.                 return error;
  85.         }
  86.         v = js_tointeger(J, idx);
  87.         js_endtry(J);
  88.         return v;
  89. }
  90.  
  91. int js_tryboolean(js_State *J, int idx, int error)
  92. {
  93.         int v;
  94.         if (js_try(J)) {
  95.                 js_pop(J, 1);
  96.                 return error;
  97.         }
  98.         v = js_toboolean(J, idx);
  99.         js_endtry(J);
  100.         return v;
  101. }
  102.  
  103. static void js_loadstringx(js_State *J, const char *filename, const char *source, int iseval)
  104. {
  105.         js_Ast *P;
  106.         js_Function *F;
  107.  
  108.         if (js_try(J)) {
  109.                 jsP_freeparse(J);
  110.                 js_throw(J);
  111.         }
  112.  
  113.         P = jsP_parse(J, filename, source);
  114.         F = jsC_compilescript(J, P, iseval ? J->strict : J->default_strict);
  115.         jsP_freeparse(J);
  116.         js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE, iseval ? JS_CEVAL : JS_CSCRIPT);
  117.  
  118.         js_endtry(J);
  119. }
  120.  
  121. void js_loadeval(js_State *J, const char *filename, const char *source)
  122. {
  123.         js_loadstringx(J, filename, source, 1);
  124. }
  125.  
  126. void js_loadstring(js_State *J, const char *filename, const char *source)
  127. {
  128.         js_loadstringx(J, filename, source, 0);
  129. }
  130.  
  131. void js_loadfile(js_State *J, const char *filename)
  132. {
  133.         FILE *f;
  134.         char *s, *p;
  135.         int n, t;
  136.  
  137.         f = fopen(filename, "rb");
  138.         if (!f) {
  139.                 js_error(J, "cannot open file '%s': %s", filename, strerror(errno));
  140.         }
  141.  
  142.         if (fseek(f, 0, SEEK_END) < 0) {
  143.                 fclose(f);
  144.                 js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
  145.         }
  146.  
  147.         n = ftell(f);
  148.         if (n < 0) {
  149.                 fclose(f);
  150.                 js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno));
  151.         }
  152.  
  153.         if (fseek(f, 0, SEEK_SET) < 0) {
  154.                 fclose(f);
  155.                 js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
  156.         }
  157.  
  158.         if (js_try(J)) {
  159.                 fclose(f);
  160.                 js_throw(J);
  161.         }
  162.         s = js_malloc(J, n + 1); /* add space for string terminator */
  163.         js_endtry(J);
  164.  
  165.         t = fread(s, 1, (size_t)n, f);
  166.         if (t != n) {
  167.                 js_free(J, s);
  168.                 fclose(f);
  169.                 js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno));
  170.         }
  171.  
  172.         s[n] = 0; /* zero-terminate string containing file data */
  173.  
  174.         if (js_try(J)) {
  175.                 js_free(J, s);
  176.                 fclose(f);
  177.                 js_throw(J);
  178.         }
  179.  
  180.         /* skip first line if it starts with "#!" */
  181.         p = s;
  182.         if (p[0] == '#' && p[1] == '!') {
  183.                 p += 2;
  184.                 while (*p && *p != '\n')
  185.                         ++p;
  186.         }
  187.  
  188.         js_loadstring(J, filename, p);
  189.  
  190.         js_free(J, s);
  191.         fclose(f);
  192.         js_endtry(J);
  193. }
  194.  
  195. int js_dostring(js_State *J, const char *source)
  196. {
  197.         if (js_try(J)) {
  198.                 js_report(J, js_trystring(J, -1, "Error"));
  199.                 js_pop(J, 1);
  200.                 return 1;
  201.         }
  202.         js_loadstring(J, "[string]", source);
  203.         js_pushundefined(J);
  204.         js_call(J, 0);
  205.         js_pop(J, 1);
  206.         js_endtry(J);
  207.         return 0;
  208. }
  209.  
  210. int js_dofile(js_State *J, const char *filename)
  211. {
  212.         if (js_try(J)) {
  213.                 js_report(J, js_trystring(J, -1, "Error"));
  214.                 js_pop(J, 1);
  215.                 return 1;
  216.         }
  217.         js_loadfile(J, filename);
  218.         js_pushundefined(J);
  219.         js_call(J, 0);
  220.         js_pop(J, 1);
  221.         js_endtry(J);
  222.         return 0;
  223. }
  224.  
  225. js_Panic js_atpanic(js_State *J, js_Panic panic)
  226. {
  227.         js_Panic old = J->panic;
  228.         J->panic = panic;
  229.         return old;
  230. }
  231.  
  232. void js_report(js_State *J, const char *message)
  233. {
  234.         if (J->report)
  235.                 J->report(J, message);
  236. }
  237.  
  238. void js_setreport(js_State *J, js_Report report)
  239. {
  240.         J->report = report;
  241. }
  242.  
  243. void js_setcontext(js_State *J, void *uctx)
  244. {
  245.         J->uctx = uctx;
  246. }
  247.  
  248. void *js_getcontext(js_State *J)
  249. {
  250.         return J->uctx;
  251. }
  252.  
  253. js_State *js_newstate(js_Alloc alloc, void *actx, int flags)
  254. {
  255.         js_State *J;
  256.  
  257.         assert(sizeof(js_Value) == 16);
  258.         assert(soffsetof(js_Value, type) == 15);
  259.  
  260.         if (!alloc)
  261.                 alloc = js_defaultalloc;
  262.  
  263.         J = alloc(actx, NULL, sizeof *J);
  264.         if (!J)
  265.                 return NULL;
  266.         memset(J, 0, sizeof(*J));
  267.         J->actx = actx;
  268.         J->alloc = alloc;
  269.  
  270.         if (flags & JS_STRICT)
  271.                 J->strict = J->default_strict = 1;
  272.  
  273.         J->trace[0].name = "-top-";
  274.         J->trace[0].file = "native";
  275.         J->trace[0].line = 0;
  276.  
  277.         J->report = js_defaultreport;
  278.         J->panic = js_defaultpanic;
  279.  
  280.         J->stack = alloc(actx, NULL, JS_STACKSIZE * sizeof *J->stack);
  281.         if (!J->stack) {
  282.                 alloc(actx, NULL, 0);
  283.                 return NULL;
  284.         }
  285.  
  286.         J->gcmark = 1;
  287.         J->nextref = 0;
  288.         J->gcthresh = 0; /* reaches stability within ~ 2-5 GC cycles */
  289.  
  290.         J->R = jsV_newobject(J, JS_COBJECT, NULL);
  291.         J->G = jsV_newobject(J, JS_COBJECT, NULL);
  292.         J->E = jsR_newenvironment(J, J->G, NULL);
  293.         J->GE = J->E;
  294.  
  295.         jsB_init(J);
  296.  
  297.         return J;
  298. }
  299.