static void Ap_forEach(js_State *J) { int hasthis = js_gettop(J) >= 3; int k, len; if (!js_iscallable(J, 1)) js_typeerror(J, "callback is not a function"); len = js_getlength(J, 0); for (k = 0; k < len; ++k) { if (js_hasindex(J, 0, k)) { js_copy(J, 1); if (hasthis) js_copy(J, 2); else js_pushundefined(J); js_copy(J, -3); js_pushnumber(J, k); js_copy(J, 0); js_call(J, 3); js_pop(J, 2); } } js_pushundefined(J); }
static int compare(js_State *J, unsigned int x, unsigned int y, int *hasx, int *hasy, int hasfn) { const char *sx, *sy; int c; *hasx = js_hasindex(J, 0, x); *hasy = js_hasindex(J, 0, y); if (*hasx && *hasy) { int unx = js_isundefined(J, -2); int uny = js_isundefined(J, -1); if (unx && uny) return 0; if (unx) return 1; if (uny) return -1; if (hasfn) { js_copy(J, 1); /* copy function */ js_pushundefinedthis(J); /* set this object */ js_copy(J, -4); /* copy x */ js_copy(J, -4); /* copy y */ js_call(J, 2); c = js_tonumber(J, -1); js_pop(J, 1); return c; } sx = js_tostring(J, -2); sy = js_tostring(J, -1); return strcmp(sx, sy); } if (*hasx) return -1; if (*hasy) return 1; return 0; }
static void Ap_filter(js_State *J) { int hasthis = js_gettop(J) >= 3; int k, to, len; if (!js_iscallable(J, 1)) js_typeerror(J, "callback is not a function"); js_newarray(J); to = 0; len = js_getlength(J, 0); for (k = 0; k < len; ++k) { if (js_hasindex(J, 0, k)) { js_copy(J, 1); if (hasthis) js_copy(J, 2); else js_pushundefined(J); js_copy(J, -3); js_pushnumber(J, k); js_copy(J, 0); js_call(J, 3); if (js_toboolean(J, -1)) { js_pop(J, 1); js_setindex(J, -2, to++); } else { js_pop(J, 2); } } } }
static void Sp_replace_string(js_State *J) { const char *source, *needle, *s, *r; js_Buffer *sb = NULL; int n; source = js_tostring(J, 0); needle = js_tostring(J, 1); s = strstr(source, needle); if (!s) { js_copy(J, 0); return; } n = strlen(needle); if (js_iscallable(J, 2)) { js_copy(J, 2); js_pushglobal(J); js_pushlstring(J, s, n); /* arg 1: substring that matched */ js_pushnumber(J, s - source); /* arg 2: offset within search string */ js_copy(J, 0); /* arg 3: search string */ js_call(J, 3); r = js_tostring(J, -1); js_putm(J, &sb, source, s); js_puts(J, &sb, r); js_puts(J, &sb, s + n); js_putc(J, &sb, 0); js_pop(J, 1); } else { r = js_tostring(J, 2); js_putm(J, &sb, source, s); while (*r) { if (*r == '$') { switch (*(++r)) { case '$': js_putc(J, &sb, '$'); break; case '&': js_putm(J, &sb, s, s + n); break; case '`': js_putm(J, &sb, source, s); break; case '\'': js_puts(J, &sb, s + n); break; default: js_putc(J, &sb, '$'); js_putc(J, &sb, *r); break; } ++r; } else { js_putc(J, &sb, *r++); } } js_puts(J, &sb, s + n); js_putc(J, &sb, 0); } if (js_try(J)) { js_free(J, sb); js_throw(J); } js_pushstring(J, sb ? sb->s : ""); js_endtry(J); js_free(J, sb); }
static void Ap_sort(js_State *J) { struct sortslot *array = NULL; int i, n, len; len = js_getlength(J, 0); if (len <= 0) { js_copy(J, 0); return; } if (len >= INT_MAX / (int)sizeof(*array)) js_rangeerror(J, "array is too large to sort"); array = js_malloc(J, len * sizeof *array); /* Holding objects where the GC cannot see them is illegal, but if we * don't allow the GC to run we can use qsort() on a temporary array of * js_Values for fast sorting. */ ++J->gcpause; if (js_try(J)) { --J->gcpause; js_free(J, array); js_throw(J); } n = 0; for (i = 0; i < len; ++i) { if (js_hasindex(J, 0, i)) { array[n].v = *js_tovalue(J, -1); array[n].J = J; js_pop(J, 1); ++n; } } qsort(array, n, sizeof *array, sortcmp); for (i = 0; i < n; ++i) { js_pushvalue(J, array[i].v); js_setindex(J, 0, i); } for (i = n; i < len; ++i) { js_delindex(J, 0, i); } --J->gcpause; js_endtry(J); js_free(J, array); js_copy(J, 0); }
static void wrapgetter(js_State *J) { pdf_jsimp_obj *ret; pdf_jsimp_getter *get; const char *type; void *jsctx; void *obj; js_getregistry(J, "jsctx"); jsctx = js_touserdata(J, "jsctx", -1); js_pop(J, 1); js_currentfunction(J); { js_getproperty(J, -1, "__get"); get = js_touserdata(J, "getter", -1); js_pop(J, 1); js_getproperty(J, -1, "__type"); type = js_tostring(J, -1); js_pop(J, 1); } js_pop(J, 1); if (js_isuserdata(J, type, 0)) obj = js_touserdata(J, type, 0); else obj = NULL; ret = get(jsctx, obj); if (ret) js_copy(J, IDX(ret)); else js_pushundefined(J); }
static int sortcmp(const void *avoid, const void *bvoid) { const struct sortslot *aslot = avoid, *bslot = bvoid; const js_Value *a = &aslot->v, *b = &bslot->v; js_State *J = aslot->J; const char *sx, *sy; int c; int unx = (a->type == JS_TUNDEFINED); int uny = (b->type == JS_TUNDEFINED); if (unx) return !uny; if (uny) return -1; if (js_iscallable(J, 1)) { js_copy(J, 1); /* copy function */ js_pushundefined(J); js_pushvalue(J, *a); js_pushvalue(J, *b); js_call(J, 2); c = js_tonumber(J, -1); js_pop(J, 1); } else { js_pushvalue(J, *a); js_pushvalue(J, *b); sx = js_tostring(J, -2); sy = js_tostring(J, -1); c = strcmp(sx, sy); js_pop(J, 2); } return c; }
static void Ap_reverse(js_State *J) { unsigned int len, middle, lower; len = js_getlength(J, 0); middle = len / 2; lower = 0; while (lower != middle) { unsigned int upper = len - lower - 1; int haslower = js_hasindex(J, 0, lower); int hasupper = js_hasindex(J, 0, upper); if (haslower && hasupper) { js_setindex(J, 0, lower); js_setindex(J, 0, upper); } else if (hasupper) { js_setindex(J, 0, lower); js_delindex(J, 0, upper); } else if (haslower) { js_setindex(J, 0, upper); js_delindex(J, 0, lower); } ++lower; } js_copy(J, 0); }
static void js_setvar(js_State *J, const char *name) { js_Environment *E = J->E; do { js_Property *ref = jsV_getproperty(J, E->variables, name); if (ref) { if (ref->setter) { js_pushobject(J, ref->setter); js_pushobject(J, E->variables); js_copy(J, -3); js_call(J, 1); js_pop(J, 1); return; } if (!(ref->atts & JS_READONLY)) ref->value = *stackidx(J, -1); else if (J->strict) js_typeerror(J, "'%s' is read-only", name); return; } E = E->outer; } while (E); if (J->strict) js_referenceerror(J, "assignment to undeclared variable '%s'", name); jsR_setproperty(J, J->G, name, stackidx(J, -1)); }
static void Fp_apply(js_State *J) { int i, n; if (!js_iscallable(J, 0)) js_typeerror(J, "not a function"); js_copy(J, 0); js_copy(J, 1); n = js_getlength(J, 2); for (i = 0; i < n; ++i) js_getindex(J, 2, i); js_call(J, n); }
static void O_preventExtensions(js_State *J) { if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); js_toobject(J, 1)->extensible = 0; js_copy(J, 1); }
static void O_defineProperty(js_State *J) { if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); if (!js_isobject(J, 3)) js_typeerror(J, "not an object"); ToPropertyDescriptor(J, js_toobject(J, 1), js_tostring(J, 2), js_toobject(J, 3)); js_copy(J, 1); }
static void Ap_unshift(js_State *J) { unsigned int i, top = js_gettop(J); unsigned int k, len; len = js_getlength(J, 0); for (k = len; k > 0; --k) { int from = k - 1; int to = k + top - 2; if (js_hasindex(J, 0, from)) js_setindex(J, 0, to); else js_delindex(J, 0, to); } for (i = 1; i < top; ++i) { js_copy(J, i); js_setindex(J, 0, i - 1); } js_setlength(J, 0, len + top - 1); js_pushnumber(J, len + top - 1); }
static void Ap_sort(js_State *J) { unsigned int len, i, k; int hasx, hasy, hasfn; len = js_getlength(J, 0); hasfn = js_iscallable(J, 1); for (i = 1; i < len; ++i) { k = i; while (k > 0 && compare(J, k - 1, k, &hasx, &hasy, hasfn) > 0) { if (hasx && hasy) { js_setindex(J, 0, k - 1); js_setindex(J, 0, k); } else if (hasx) { js_delindex(J, 0, k - 1); js_setindex(J, 0, k); } else if (hasy) { js_setindex(J, 0, k - 1); js_delindex(J, 0, k); } --k; } } js_copy(J, 0); }
void js_eval(js_State *J) { if (!js_isstring(J, -1)) return; js_loadeval(J, "(eval)", js_tostring(J, -1)); js_rot2pop1(J); js_copy(J, 0); /* copy 'this' */ js_call(J, 0); }
static void jsB_eval(js_State *J) { if (!js_isstring(J, -1)) { js_copy(J, 1); return; } js_loadstring(J, "(eval)", js_tostring(J, -1)); js_pushglobal(J); js_call(J, 0); }
static void Sp_split(js_State *J) { if (js_isundefined(J, 1)) { js_newarray(J); js_copy(J, 0); js_setindex(J, -2, 0); } else if (js_isregexp(J, 1)) { Sp_split_regexp(J); } else { Sp_split_string(J); } }
static void Fp_call(js_State *J) { unsigned int i, top = js_gettop(J); if (!js_iscallable(J, 0)) js_typeerror(J, "not a function"); for (i = 0; i < top; ++i) js_copy(J, i); js_call(J, top - 2); }
static void jsB_new_Array(js_State *J) { unsigned int i, top = js_gettop(J); js_newarray(J); if (top == 2) { if (js_isnumber(J, 1)) { js_copy(J, 1); js_setproperty(J, -2, "length"); } else { js_copy(J, 1); js_setindex(J, -2, 0); } } else { for (i = 1; i < top; ++i) { js_copy(J, i); js_setindex(J, -2, i - 1); } } }
static void Ap_reduceRight(js_State *J) { int hasinitial = js_gettop(J) >= 3; int k, len; if (!js_iscallable(J, 1)) js_typeerror(J, "callback is not a function"); len = js_getlength(J, 0); k = len - 1; if (len == 0 && !hasinitial) js_typeerror(J, "no initial value"); /* initial value of accumulator */ if (hasinitial) js_copy(J, 2); else { while (k >= 0) if (js_hasindex(J, 0, k--)) break; if (k < 0) js_typeerror(J, "no initial value"); } while (k >= 0) { if (js_hasindex(J, 0, k)) { js_copy(J, 1); js_pushundefined(J); js_rot(J, 4); /* accumulator on top */ js_rot(J, 4); /* property on top */ js_pushnumber(J, k); js_copy(J, 0); js_call(J, 4); /* calculate new accumulator */ } --k; } /* return accumulator */ }
static void Ap_splice(js_State *J) { unsigned int top = js_gettop(J); unsigned int len, start, del, add, k; double f; js_newarray(J); len = js_getlength(J, 0); f = js_tointeger(J, 1); if (f < 0) f = f + len; start = f < 0 ? 0 : f > len ? len : f; f = js_tointeger(J, 2); del = f < 0 ? 0 : f > len - start ? len - start : f; /* copy deleted items to return array */ for (k = 0; k < del; ++k) if (js_hasindex(J, 0, start + k)) js_setindex(J, -2, k); js_setlength(J, -1, del); /* shift the tail to resize the hole left by deleted items */ add = top - 3; if (add < del) { for (k = start; k < len - del; ++k) { if (js_hasindex(J, 0, k + del)) js_setindex(J, 0, k + add); else js_delindex(J, 0, k + add); } for (k = len; k > len - del + add; --k) js_delindex(J, 0, k - 1); } else if (add > del) { for (k = len - del; k > start; --k) { if (js_hasindex(J, 0, k + del - 1)) js_setindex(J, 0, k + add - 1); else js_delindex(J, 0, k + add - 1); } } /* copy new items into the hole */ for (k = 0; k < add; ++k) { js_copy(J, 3 + k); js_setindex(J, 0, start + k); } js_setlength(J, 0, len - del + add); }
/* prototype -- constructor */ void js_newcconstructor(js_State *J, js_CFunction cfun, js_CFunction ccon, unsigned int length) { js_Object *obj = jsV_newobject(J, JS_CCFUNCTION, J->Function_prototype); obj->u.c.function = cfun; obj->u.c.constructor = ccon; js_pushobject(J, obj); /* proto obj */ { js_pushnumber(J, length); js_defproperty(J, -2, "length", JS_READONLY | JS_DONTENUM | JS_DONTCONF); js_rot2(J); /* obj proto */ js_copy(J, -2); /* obj proto obj */ js_defproperty(J, -2, "constructor", JS_DONTENUM); js_defproperty(J, -2, "prototype", JS_READONLY | JS_DONTENUM | JS_DONTCONF); } }
static void Fp_bind(js_State *J) { unsigned int i, top = js_gettop(J); unsigned int n; if (!js_iscallable(J, 0)) js_typeerror(J, "not a function"); n = js_getlength(J, 0); if (n > top - 2) n -= top - 2; else n = 0; js_newcconstructor(J, callbound, constructbound, "[bind]", n); /* Reuse target function's prototype for HasInstance check. */ js_getproperty(J, 0, "prototype"); js_defproperty(J, -2, "prototype", JS_READONLY | JS_DONTENUM | JS_DONTCONF); /* target function */ js_copy(J, 0); js_defproperty(J, -2, "__TargetFunction__", JS_READONLY | JS_DONTENUM | JS_DONTCONF); /* bound this */ js_copy(J, 1); js_defproperty(J, -2, "__BoundThis__", JS_READONLY | JS_DONTENUM | JS_DONTCONF); /* bound arguments */ js_newarray(J); for (i = 2; i < top; ++i) { js_copy(J, i); js_setindex(J, -2, i - 2); } js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF); }
static void O_freeze(js_State *J) { js_Object *obj; js_Property *ref; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); obj->extensible = 0; for (ref = obj->head; ref; ref = ref->next) ref->atts |= JS_READONLY | JS_DONTCONF; js_copy(J, 1); }
static void Ap_push(js_State *J) { unsigned int i, top = js_gettop(J); unsigned int n; n = js_getlength(J, 0); for (i = 1; i < top; ++i, ++n) { js_copy(J, i); js_setindex(J, 0, n); } js_setlength(J, 0, n); js_pushnumber(J, n); }
void js_newfunction(js_State *J, js_Function *fun, js_Environment *scope) { js_Object *obj = jsV_newobject(J, JS_CFUNCTION, J->Function_prototype); obj->u.f.function = fun; obj->u.f.scope = scope; js_pushobject(J, obj); { js_pushnumber(J, fun->numparams); js_defproperty(J, -2, "length", JS_READONLY | JS_DONTENUM | JS_DONTCONF); js_newobject(J); { js_copy(J, -2); js_defproperty(J, -2, "constructor", JS_DONTENUM); } js_defproperty(J, -2, "prototype", JS_DONTCONF); } }
static void Sp_match(js_State *J) { js_Regexp *re; const char *text; unsigned int len; const char *a, *b, *c, *e; Resub m; text = js_tostring(J, 0); if (js_isregexp(J, 1)) js_copy(J, 1); else if (js_isundefined(J, 1)) js_newregexp(J, "", 0); else js_newregexp(J, js_tostring(J, 1), 0); re = js_toregexp(J, -1); if (!(re->flags & JS_REGEXP_G)) { js_RegExp_prototype_exec(J, re, text); return; } re->last = 0; js_newarray(J); len = 0; a = text; e = text + strlen(text); while (a <= e) { if (js_regexec(re->prog, a, &m, a > text ? REG_NOTBOL : 0)) break; b = m.sub[0].sp; c = m.sub[0].ep; js_pushlstring(J, b, c - b); js_setindex(J, -2, len++); a = c; if (c - b == 0) ++a; } }
static void wrapmethod(js_State *J) { pdf_jsimp_obj *args[MAXARGS]; pdf_jsimp_obj *ret; pdf_jsimp_method *meth; const char *type; void *jsctx; void *obj; int i; int argc = js_gettop(J) - 1; js_getregistry(J, "jsctx"); jsctx = js_touserdata(J, "jsctx", -1); js_pop(J, 1); js_currentfunction(J); { js_getproperty(J, -1, "__call"); meth = js_touserdata(J, "method", -1); js_pop(J, 1); js_getproperty(J, -1, "__type"); type = js_tostring(J, -1); js_pop(J, 1); } js_pop(J, 1); if (js_isuserdata(J, type, 0)) obj = js_touserdata(J, type, 0); else obj = NULL; if (argc > MAXARGS) js_rangeerror(J, "too many arguments"); for (i = 0; i < argc; ++i) args[i] = OBJ(i+1); ret = meth(jsctx, obj, argc, args); if (ret) js_copy(J, IDX(ret)); else js_pushundefined(J); }
static void O_defineProperties(js_State *J) { js_Object *props; js_Property *ref; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); if (!js_isobject(J, 2)) js_typeerror(J, "not an object"); props = js_toobject(J, 2); for (ref = props->head; ref; ref = ref->next) { if (!(ref->atts & JS_DONTENUM)) { js_pushvalue(J, ref->value); ToPropertyDescriptor(J, js_toobject(J, 1), ref->name, js_toobject(J, -1)); js_pop(J, 1); } } js_copy(J, 1); }
static void jsR_callfunction(js_State *J, unsigned int n, js_Function *F, js_Environment *scope) { js_Value v; unsigned int i; scope = jsR_newenvironment(J, jsV_newobject(J, JS_COBJECT, NULL), scope); jsR_savescope(J, scope); if (F->arguments) { js_newobject(J); if (!J->strict) { js_currentfunction(J); js_defproperty(J, -2, "callee", JS_DONTENUM); } js_pushnumber(J, n); js_defproperty(J, -2, "length", JS_DONTENUM); for (i = 0; i < n; ++i) { js_copy(J, i + 1); js_setindex(J, -2, i); } js_initvar(J, "arguments", -1); js_pop(J, 1); } for (i = 0; i < F->numparams; ++i) { if (i < n) js_initvar(J, F->vartab[i], i + 1); else { js_pushundefined(J); js_initvar(J, F->vartab[i], -1); js_pop(J, 1); } } js_pop(J, n); jsR_run(J, F); v = *stackidx(J, -1); TOP = --BOT; /* clear stack */ js_pushvalue(J, v); jsR_restorescope(J); }