void js_concat(js_State *J) { js_toprimitive(J, -2, JS_HNONE); js_toprimitive(J, -1, JS_HNONE); if (js_isstring(J, -2) || js_isstring(J, -1)) { const char *sa = js_tostring(J, -2); const char *sb = js_tostring(J, -1); /* TODO: create js_String directly */ char *sab = js_malloc(J, strlen(sa) + strlen(sb) + 1); strcpy(sab, sa); strcat(sab, sb); if (js_try(J)) { js_free(J, sab); js_throw(J); } js_pop(J, 2); js_pushstring(J, sab); js_endtry(J); js_free(J, sab); } else { double x = js_tonumber(J, -2); double y = js_tonumber(J, -1); js_pop(J, 2); js_pushnumber(J, x + y); } }
static void Sp_concat(js_State *J) { unsigned int i, top = js_gettop(J); unsigned int n; char * volatile out; const char *s; if (top == 1) return; s = js_tostring(J, 0); n = strlen(s); out = js_malloc(J, n + 1); strcpy(out, s); if (js_try(J)) { js_free(J, out); js_throw(J); } for (i = 1; i < top; ++i) { s = js_tostring(J, i); n += strlen(s); out = realloc(out, n + 1); strcat(out, s); } js_pushstring(J, out); js_endtry(J); js_free(J, out); }
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 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 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_join(js_State *J) { char * volatile out = NULL; const char *sep; const char *r; unsigned int seplen; unsigned int k, n, len; len = js_getlength(J, 0); if (js_isdefined(J, 1)) { sep = js_tostring(J, 1); seplen = strlen(sep); } else { sep = ","; seplen = 1; } if (len == 0) { js_pushliteral(J, ""); return; } if (js_try(J)) { js_free(J, out); js_throw(J); } n = 1; for (k = 0; k < len; ++k) { js_getindex(J, 0, k); if (js_isundefined(J, -1) || js_isnull(J, -1)) r = ""; else r = js_tostring(J, -1); n += strlen(r); if (k == 0) { out = js_malloc(J, n); strcpy(out, r); } else { n += seplen; out = realloc(out, n); strcat(out, sep); strcat(out, r); } js_pop(J, 1); } js_pushstring(J, out); js_endtry(J); js_free(J, out); }
static void wrapsetter(js_State *J) { pdf_jsimp_setter *set; 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, "__set"); set = js_touserdata(J, "setter", -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; set(jsctx, obj, OBJ(1)); js_pushundefined(J); }
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); }
int js_compare(js_State *J, int *okay) { js_toprimitive(J, -2, JS_HNUMBER); js_toprimitive(J, -1, JS_HNUMBER); *okay = 1; if (js_isstring(J, -2) && js_isstring(J, -1)) { return strcmp(js_tostring(J, -2), js_tostring(J, -1)); } else { double x = js_tonumber(J, -2); double y = js_tonumber(J, -1); if (isnan(x) || isnan(y)) *okay = 0; return x < y ? -1 : x > y ? 1 : 0; } }
int js_dostring(js_State *J, const char *source, int report) { if (js_try(J)) { fprintf(stderr, "libjs: %s\n", js_tostring(J, -1)); js_pop(J, 1); return 1; } js_loadstring(J, "(string)", source); js_pushglobal(J); js_call(J, 0); if (report) printf("%s\n", js_tostring(J, -1)); js_pop(J, 1); js_endtry(J); return 0; }
static void O_getOwnPropertyDescriptor(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); ref = jsV_getproperty(J, obj, js_tostring(J, 2)); if (!ref) js_pushundefined(J); else { js_newobject(J); if (!ref->getter && !ref->setter) { js_pushvalue(J, ref->value); js_setproperty(J, -2, "value"); js_pushboolean(J, !(ref->atts & JS_READONLY)); js_setproperty(J, -2, "writable"); } else { if (ref->getter) js_pushobject(J, ref->getter); else js_pushundefined(J); js_setproperty(J, -2, "get"); if (ref->setter) js_pushobject(J, ref->setter); else js_pushundefined(J); js_setproperty(J, -2, "set"); } js_pushboolean(J, !(ref->atts & JS_DONTENUM)); js_setproperty(J, -2, "enumerable"); js_pushboolean(J, !(ref->atts & JS_DONTCONF)); js_setproperty(J, -2, "configurable"); } }
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 Op_hasOwnProperty(js_State *J) { js_Object *self = js_toobject(J, 0); const char *name = js_tostring(J, 1); js_Property *ref = jsV_getownproperty(J, self, name); js_pushboolean(J, ref != NULL); }
static void Op_propertyIsEnumerable(js_State *J) { js_Object *self = js_toobject(J, 0); const char *name = js_tostring(J, 1); js_Property *ref = jsV_getownproperty(J, self, name); js_pushboolean(J, ref && !(ref->atts & JS_DONTENUM)); }
static void Sp_lastIndexOf(js_State *J) { const char *haystack = js_tostring(J, 0); const char *needle = js_tostring(J, 1); int pos = js_isdefined(J, 2) ? js_tointeger(J, 2) : strlen(haystack); int len = strlen(needle); int k = 0, last = -1; Rune rune; while (*haystack && k <= pos) { if (!strncmp(haystack, needle, len)) last = k; haystack += chartorune(&rune, haystack); ++k; } js_pushnumber(J, last); }
static void JSON_parse(js_State *J) { const char *source = js_tostring(J, 1); jsY_initlex(J, "JSON", source); jsonnext(J); jsonvalue(J); // TODO: reviver Walk() }
static void Sp_split_regexp(js_State *J) { js_Regexp *re; const char *text; unsigned int limit, len, k; const char *p, *a, *b, *c, *e; Resub m; text = js_tostring(J, 0); re = js_toregexp(J, 1); limit = js_isdefined(J, 2) ? js_touint32(J, 2) : 1 << 30; js_newarray(J); len = 0; e = text + strlen(text); /* splitting the empty string */ if (e == 0) { if (js_regexec(re->prog, text, &m, 0)) { if (len == limit) return; js_pushliteral(J, ""); js_setindex(J, -2, 0); } return; } p = a = text; while (a < e) { if (js_regexec(re->prog, a, &m, a > text ? REG_NOTBOL : 0)) break; /* no match */ b = m.sub[0].sp; c = m.sub[0].ep; /* empty string at end of last match */ if (b == p) { ++a; continue; } if (len == limit) return; js_pushlstring(J, p, b - p); js_setindex(J, -2, len++); for (k = 1; k < m.nsub; ++k) { if (len == limit) return; js_pushlstring(J, m.sub[k].sp, m.sub[k].ep - m.sub[k].sp); js_setindex(J, -2, len++); } a = p = c; } if (len == limit) return; js_pushstring(J, p); js_setindex(J, -2, len); }
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 Sp_indexOf(js_State *J) { const char *haystack = js_tostring(J, 0); const char *needle = js_tostring(J, 1); int pos = js_tointeger(J, 2); int len = strlen(needle); int k = 0; Rune rune; while (*haystack) { if (k >= pos && !strncmp(haystack, needle, len)) { js_pushnumber(J, k); return; } haystack += chartorune(&rune, haystack); ++k; } js_pushnumber(J, -1); }
int eval_print(js_State *J, const char *source) { if (js_ploadstring(J, "[string]", source)) { fprintf(stderr, "%s\n", js_tostring(J, -1)); js_pop(J, 1); return 1; } js_pushglobal(J); if (js_pcall(J, 0)) { fprintf(stderr, "%s\n", js_tostring(J, -1)); js_pop(J, 1); return 1; } if (js_isdefined(J, -1)) printf("%s\n", js_tostring(J, -1)); js_pop(J, 1); return 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 Sp_charCodeAt(js_State *J) { const char *s = js_tostring(J, 0); int pos = js_tointeger(J, 1); Rune rune = js_runeat(J, s, pos); if (rune > 0) js_pushnumber(J, rune); else js_pushnumber(J, NAN); }
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 jsB_write(js_State *J) { int i, top = js_gettop(J); for (i = 1; i < top; ++i) { const char *s = js_tostring(J, i); if (i > 1) putchar(' '); fputs(s, stdout); } js_pushundefined(J); }
static void Sp_trim(js_State *J) { const char *s, *e; s = js_tostring(J, 0); while (istrim(*s)) ++s; e = s + strlen(s); while (e > s && istrim(e[-1])) --e; js_pushlstring(J, s, e - s); }
void js_util_dumpstack(js_State *state, int depth) { int idx; const gchar *str; for (idx = 0; idx > -depth; idx--) { str = js_tostring(state, idx); fprintf(stderr, "[%d] - %s\n", idx, str); } }
static void jsB_load(js_State *J) { int i, n = js_gettop(J); for (i = 1; i < n; ++i) { js_loadfile(J, js_tostring(J, i)); js_pushundefined(J); js_call(J, 0); js_pop(J, 1); } js_pushundefined(J); }
static void Sp_charAt(js_State *J) { char buf[UTFmax + 1]; const char *s = js_tostring(J, 0); int pos = js_tointeger(J, 1); Rune rune = js_runeat(J, s, pos); if (rune > 0) { buf[runetochar(buf, &rune)] = 0; js_pushstring(J, buf); } else { js_pushliteral(J, ""); } }
static void Sp_search(js_State *J) { js_Regexp *re; const char *text; 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 (!js_regexec(re->prog, text, &m, 0)) js_pushnumber(J, js_utfptrtoidx(text, m.sub[0].sp)); else js_pushnumber(J, -1); }
int js_dofile(js_State *J, const char *filename) { if (js_try(J)) { fprintf(stderr, "libjs: %s\n", js_tostring(J, -1)); js_pop(J, 1); return 1; } js_loadfile(J, filename); js_pushglobal(J); js_call(J, 0); js_pop(J, 1); js_endtry(J); return 0; }