Subversion Repositories Kolibri OS

Rev

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 "jsbuiltin.h"
  6.  
  7. static void jsB_Function(js_State *J)
  8. {
  9.         int i, top = js_gettop(J);
  10.         js_Buffer *sb = NULL;
  11.         const char *body;
  12.         js_Ast *parse;
  13.         js_Function *fun;
  14.  
  15.         if (js_try(J)) {
  16.                 js_free(J, sb);
  17.                 jsP_freeparse(J);
  18.                 js_throw(J);
  19.         }
  20.  
  21.         /* p1, p2, ..., pn */
  22.         if (top > 2) {
  23.                 for (i = 1; i < top - 1; ++i) {
  24.                         if (i > 1)
  25.                                 js_putc(J, &sb, ',');
  26.                         js_puts(J, &sb, js_tostring(J, i));
  27.                 }
  28.                 js_putc(J, &sb, ')');
  29.                 js_putc(J, &sb, 0);
  30.         }
  31.  
  32.         /* body */
  33.         body = js_isdefined(J, top - 1) ? js_tostring(J, top - 1) : "";
  34.  
  35.         parse = jsP_parsefunction(J, "[string]", sb ? sb->s : NULL, body);
  36.         fun = jsC_compilefunction(J, parse);
  37.  
  38.         js_endtry(J);
  39.         js_free(J, sb);
  40.         jsP_freeparse(J);
  41.  
  42.         js_newfunction(J, fun, J->GE);
  43. }
  44.  
  45. static void jsB_Function_prototype(js_State *J)
  46. {
  47.         js_pushundefined(J);
  48. }
  49.  
  50. static void Fp_toString(js_State *J)
  51. {
  52.         js_Object *self = js_toobject(J, 0);
  53.         js_Buffer *sb = NULL;
  54.         int i;
  55.  
  56.         if (!js_iscallable(J, 0))
  57.                 js_typeerror(J, "not a function");
  58.  
  59.         if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT || self->type == JS_CEVAL) {
  60.                 js_Function *F = self->u.f.function;
  61.  
  62.                 if (js_try(J)) {
  63.                         js_free(J, sb);
  64.                         js_throw(J);
  65.                 }
  66.  
  67.                 js_puts(J, &sb, "function ");
  68.                 js_puts(J, &sb, F->name);
  69.                 js_putc(J, &sb, '(');
  70.                 for (i = 0; i < F->numparams; ++i) {
  71.                         if (i > 0) js_putc(J, &sb, ',');
  72.                         js_puts(J, &sb, F->vartab[i]);
  73.                 }
  74.                 js_puts(J, &sb, ") { [byte code] }");
  75.                 js_putc(J, &sb, 0);
  76.  
  77.                 js_pushstring(J, sb->s);
  78.                 js_endtry(J);
  79.                 js_free(J, sb);
  80.         } else if (self->type == JS_CCFUNCTION) {
  81.                 if (js_try(J)) {
  82.                         js_free(J, sb);
  83.                         js_throw(J);
  84.                 }
  85.  
  86.                 js_puts(J, &sb, "function ");
  87.                 js_puts(J, &sb, self->u.c.name);
  88.                 js_puts(J, &sb, "() { [native code] }");
  89.                 js_putc(J, &sb, 0);
  90.  
  91.                 js_pushstring(J, sb->s);
  92.                 js_endtry(J);
  93.                 js_free(J, sb);
  94.         } else {
  95.                 js_pushliteral(J, "function () { }");
  96.         }
  97. }
  98.  
  99. static void Fp_apply(js_State *J)
  100. {
  101.         int i, n;
  102.  
  103.         if (!js_iscallable(J, 0))
  104.                 js_typeerror(J, "not a function");
  105.  
  106.         js_copy(J, 0);
  107.         js_copy(J, 1);
  108.  
  109.         if (js_isnull(J, 2) || js_isundefined(J, 2)) {
  110.                 n = 0;
  111.         } else {
  112.                 n = js_getlength(J, 2);
  113.                 for (i = 0; i < n; ++i)
  114.                         js_getindex(J, 2, i);
  115.         }
  116.  
  117.         js_call(J, n);
  118. }
  119.  
  120. static void Fp_call(js_State *J)
  121. {
  122.         int i, top = js_gettop(J);
  123.  
  124.         if (!js_iscallable(J, 0))
  125.                 js_typeerror(J, "not a function");
  126.  
  127.         for (i = 0; i < top; ++i)
  128.                 js_copy(J, i);
  129.  
  130.         js_call(J, top - 2);
  131. }
  132.  
  133. static void callbound(js_State *J)
  134. {
  135.         int top = js_gettop(J);
  136.         int i, fun, args, n;
  137.  
  138.         fun = js_gettop(J);
  139.         js_currentfunction(J);
  140.         js_getproperty(J, fun, "__TargetFunction__");
  141.         js_getproperty(J, fun, "__BoundThis__");
  142.  
  143.         args = js_gettop(J);
  144.         js_getproperty(J, fun, "__BoundArguments__");
  145.         n = js_getlength(J, args);
  146.         for (i = 0; i < n; ++i)
  147.                 js_getindex(J, args, i);
  148.         js_remove(J, args);
  149.  
  150.         for (i = 1; i < top; ++i)
  151.                 js_copy(J, i);
  152.  
  153.         js_call(J, n + top - 1);
  154. }
  155.  
  156. static void constructbound(js_State *J)
  157. {
  158.         int top = js_gettop(J);
  159.         int i, fun, args, n;
  160.  
  161.         fun = js_gettop(J);
  162.         js_currentfunction(J);
  163.         js_getproperty(J, fun, "__TargetFunction__");
  164.  
  165.         args = js_gettop(J);
  166.         js_getproperty(J, fun, "__BoundArguments__");
  167.         n = js_getlength(J, args);
  168.         for (i = 0; i < n; ++i)
  169.                 js_getindex(J, args, i);
  170.         js_remove(J, args);
  171.  
  172.         for (i = 1; i < top; ++i)
  173.                 js_copy(J, i);
  174.  
  175.         js_construct(J, n + top - 1);
  176. }
  177.  
  178. static void Fp_bind(js_State *J)
  179. {
  180.         int i, top = js_gettop(J);
  181.         int n;
  182.  
  183.         if (!js_iscallable(J, 0))
  184.                 js_typeerror(J, "not a function");
  185.  
  186.         n = js_getlength(J, 0);
  187.         if (n > top - 2)
  188.                 n -= top - 2;
  189.         else
  190.                 n = 0;
  191.  
  192.         /* Reuse target function's prototype for HasInstance check. */
  193.         js_getproperty(J, 0, "prototype");
  194.         js_newcconstructor(J, callbound, constructbound, "[bind]", n);
  195.  
  196.         /* target function */
  197.         js_copy(J, 0);
  198.         js_defproperty(J, -2, "__TargetFunction__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  199.  
  200.         /* bound this */
  201.         js_copy(J, 1);
  202.         js_defproperty(J, -2, "__BoundThis__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  203.  
  204.         /* bound arguments */
  205.         js_newarray(J);
  206.         for (i = 2; i < top; ++i) {
  207.                 js_copy(J, i);
  208.                 js_setindex(J, -2, i - 2);
  209.         }
  210.         js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
  211. }
  212.  
  213. void jsB_initfunction(js_State *J)
  214. {
  215.         J->Function_prototype->u.c.name = "Function.prototype";
  216.         J->Function_prototype->u.c.function = jsB_Function_prototype;
  217.         J->Function_prototype->u.c.constructor = NULL;
  218.         J->Function_prototype->u.c.length = 0;
  219.  
  220.         js_pushobject(J, J->Function_prototype);
  221.         {
  222.                 jsB_propf(J, "Function.prototype.toString", Fp_toString, 2);
  223.                 jsB_propf(J, "Function.prototype.apply", Fp_apply, 2);
  224.                 jsB_propf(J, "Function.prototype.call", Fp_call, 1);
  225.                 jsB_propf(J, "Function.prototype.bind", Fp_bind, 1);
  226.         }
  227.         js_newcconstructor(J, jsB_Function, jsB_Function, "Function", 1);
  228.         js_defglobal(J, "Function", JS_DONTENUM);
  229. }
  230.