jsbuiltin.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "jsi.h"
  2. #include "regexp.h"
  3. static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
  4. {
  5. js_newcfunction(J, cfun, name, n);
  6. js_defglobal(J, name, JS_DONTENUM);
  7. }
  8. void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n)
  9. {
  10. const char *pname = strrchr(name, '.');
  11. pname = pname ? pname + 1 : name;
  12. js_newcfunction(J, cfun, name, n);
  13. js_defproperty(J, -2, pname, JS_DONTENUM);
  14. }
  15. void jsB_propn(js_State *J, const char *name, double number)
  16. {
  17. js_pushnumber(J, number);
  18. js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  19. }
  20. void jsB_props(js_State *J, const char *name, const char *string)
  21. {
  22. js_pushliteral(J, string);
  23. js_defproperty(J, -2, name, JS_DONTENUM);
  24. }
  25. static void jsB_parseInt(js_State *J)
  26. {
  27. const char *s = js_tostring(J, 1);
  28. int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
  29. double sign = 1;
  30. double n;
  31. char *e;
  32. while (jsY_iswhite(*s) || jsY_isnewline(*s))
  33. ++s;
  34. if (*s == '-') {
  35. ++s;
  36. sign = -1;
  37. } else if (*s == '+') {
  38. ++s;
  39. }
  40. if (radix == 0) {
  41. radix = 10;
  42. if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
  43. s += 2;
  44. radix = 16;
  45. }
  46. } else if (radix < 2 || radix > 36) {
  47. js_pushnumber(J, NAN);
  48. return;
  49. }
  50. n = js_strtol(s, &e, radix);
  51. if (s == e)
  52. js_pushnumber(J, NAN);
  53. else
  54. js_pushnumber(J, n * sign);
  55. }
  56. static void jsB_parseFloat(js_State *J)
  57. {
  58. const char *s = js_tostring(J, 1);
  59. char *e;
  60. double n;
  61. while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
  62. if (!strncmp(s, "Infinity", 8))
  63. js_pushnumber(J, INFINITY);
  64. else if (!strncmp(s, "+Infinity", 9))
  65. js_pushnumber(J, INFINITY);
  66. else if (!strncmp(s, "-Infinity", 9))
  67. js_pushnumber(J, -INFINITY);
  68. else {
  69. n = js_stringtofloat(s, &e);
  70. if (e == s)
  71. js_pushnumber(J, NAN);
  72. else
  73. js_pushnumber(J, n);
  74. }
  75. }
  76. static void jsB_isNaN(js_State *J)
  77. {
  78. double n = js_tonumber(J, 1);
  79. js_pushboolean(J, isnan(n));
  80. }
  81. static void jsB_isFinite(js_State *J)
  82. {
  83. double n = js_tonumber(J, 1);
  84. js_pushboolean(J, isfinite(n));
  85. }
  86. static void Encode(js_State *J, const char *str_, const char *unescaped)
  87. {
  88. /* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
  89. const char * volatile str = str_;
  90. js_Buffer *sb = NULL;
  91. static const char *HEX = "0123456789ABCDEF";
  92. if (js_try(J)) {
  93. js_free(J, sb);
  94. js_throw(J);
  95. }
  96. while (*str) {
  97. int c = (unsigned char) *str++;
  98. if (strchr(unescaped, c))
  99. js_putc(J, &sb, c);
  100. else {
  101. js_putc(J, &sb, '%');
  102. js_putc(J, &sb, HEX[(c >> 4) & 0xf]);
  103. js_putc(J, &sb, HEX[c & 0xf]);
  104. }
  105. }
  106. js_putc(J, &sb, 0);
  107. js_pushstring(J, sb ? sb->s : "");
  108. js_endtry(J);
  109. js_free(J, sb);
  110. }
  111. static void Decode(js_State *J, const char *str_, const char *reserved)
  112. {
  113. /* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
  114. const char * volatile str = str_;
  115. js_Buffer *sb = NULL;
  116. int a, b;
  117. if (js_try(J)) {
  118. js_free(J, sb);
  119. js_throw(J);
  120. }
  121. while (*str) {
  122. int c = (unsigned char) *str++;
  123. if (c != '%')
  124. js_putc(J, &sb, c);
  125. else {
  126. if (!str[0] || !str[1])
  127. js_urierror(J, "truncated escape sequence");
  128. a = *str++;
  129. b = *str++;
  130. if (!jsY_ishex(a) || !jsY_ishex(b))
  131. js_urierror(J, "invalid escape sequence");
  132. c = jsY_tohex(a) << 4 | jsY_tohex(b);
  133. if (!strchr(reserved, c))
  134. js_putc(J, &sb, c);
  135. else {
  136. js_putc(J, &sb, '%');
  137. js_putc(J, &sb, a);
  138. js_putc(J, &sb, b);
  139. }
  140. }
  141. }
  142. js_putc(J, &sb, 0);
  143. js_pushstring(J, sb ? sb->s : "");
  144. js_endtry(J);
  145. js_free(J, sb);
  146. }
  147. #define URIRESERVED ";/?:@&=+$,"
  148. #define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  149. #define URIDIGIT "0123456789"
  150. #define URIMARK "-_.!~*'()"
  151. #define URIUNESCAPED URIALPHA URIDIGIT URIMARK
  152. static void jsB_decodeURI(js_State *J)
  153. {
  154. Decode(J, js_tostring(J, 1), URIRESERVED "#");
  155. }
  156. static void jsB_decodeURIComponent(js_State *J)
  157. {
  158. Decode(J, js_tostring(J, 1), "");
  159. }
  160. static void jsB_encodeURI(js_State *J)
  161. {
  162. Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
  163. }
  164. static void jsB_encodeURIComponent(js_State *J)
  165. {
  166. Encode(J, js_tostring(J, 1), URIUNESCAPED);
  167. }
  168. void jsB_init(js_State *J)
  169. {
  170. /* Create the prototype objects here, before the constructors */
  171. J->Object_prototype = jsV_newobject(J, JS_COBJECT, NULL);
  172. J->Array_prototype = jsV_newobject(J, JS_CARRAY, J->Object_prototype);
  173. J->Function_prototype = jsV_newobject(J, JS_CCFUNCTION, J->Object_prototype);
  174. J->Boolean_prototype = jsV_newobject(J, JS_CBOOLEAN, J->Object_prototype);
  175. J->Number_prototype = jsV_newobject(J, JS_CNUMBER, J->Object_prototype);
  176. J->String_prototype = jsV_newobject(J, JS_CSTRING, J->Object_prototype);
  177. J->Date_prototype = jsV_newobject(J, JS_CDATE, J->Object_prototype);
  178. J->RegExp_prototype = jsV_newobject(J, JS_CREGEXP, J->Object_prototype);
  179. J->RegExp_prototype->u.r.prog = js_regcompx(J->alloc, J->actx, "(?:)", 0, NULL);
  180. J->RegExp_prototype->u.r.source = js_strdup(J, "(?:)");
  181. /* All the native error types */
  182. J->Error_prototype = jsV_newobject(J, JS_CERROR, J->Object_prototype);
  183. J->EvalError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
  184. J->RangeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
  185. J->ReferenceError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
  186. J->SyntaxError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
  187. J->TypeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
  188. J->URIError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
  189. /* Create the constructors and fill out the prototype objects */
  190. jsB_initobject(J);
  191. jsB_initarray(J);
  192. jsB_initfunction(J);
  193. jsB_initboolean(J);
  194. jsB_initnumber(J);
  195. jsB_initstring(J);
  196. jsB_initregexp(J);
  197. jsB_initdate(J);
  198. jsB_initerror(J);
  199. jsB_initmath(J);
  200. jsB_initjson(J);
  201. /* Initialize the global object */
  202. js_pushnumber(J, NAN);
  203. js_defglobal(J, "NaN", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  204. js_pushnumber(J, INFINITY);
  205. js_defglobal(J, "Infinity", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  206. js_pushundefined(J);
  207. js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  208. jsB_globalf(J, "parseInt", jsB_parseInt, 1);
  209. jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
  210. jsB_globalf(J, "isNaN", jsB_isNaN, 1);
  211. jsB_globalf(J, "isFinite", jsB_isFinite, 1);
  212. jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
  213. jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
  214. jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
  215. jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
  216. }