From 96a54896ee453a453b25a9c9e5c6ba8d0caba7cc Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 16 Dec 2015 16:03:52 +0100 Subject: Drop 'jsimp' abstraction and use mujs directly. --- source/pdf/js/pdf-js.c | 1057 +++++++++++++++----------------------- source/pdf/js/pdf-jsimp-cpp.c | 225 -------- source/pdf/js/pdf-jsimp-cpp.h | 29 -- source/pdf/js/pdf-jsimp-jscore.c | 518 ------------------- source/pdf/js/pdf-jsimp-mu.c | 318 ------------ source/pdf/js/pdf-jsimp-v8.cpp | 474 ----------------- source/pdf/pdf-event.c | 10 +- source/pdf/pdf-form.c | 16 +- source/pdf/pdf-xref.c | 2 +- 9 files changed, 423 insertions(+), 2226 deletions(-) delete mode 100644 source/pdf/js/pdf-jsimp-cpp.c delete mode 100644 source/pdf/js/pdf-jsimp-cpp.h delete mode 100644 source/pdf/js/pdf-jsimp-jscore.c delete mode 100644 source/pdf/js/pdf-jsimp-mu.c delete mode 100644 source/pdf/js/pdf-jsimp-v8.cpp (limited to 'source/pdf') diff --git a/source/pdf/js/pdf-js.c b/source/pdf/js/pdf-js.c index 6eea8c30..c03429a7 100644 --- a/source/pdf/js/pdf-js.c +++ b/source/pdf/js/pdf-js.c @@ -1,7 +1,5 @@ #include "mupdf/pdf.h" - -/* TODO: js->doc -> doc */ -/* TODO: js->ctx -> ctx */ +#include "mujs.h" struct pdf_js_s { @@ -9,746 +7,540 @@ struct pdf_js_s pdf_document *doc; pdf_obj *form; pdf_js_event event; - pdf_jsimp *imp; - pdf_jsimp_type *doctype; - pdf_jsimp_type *eventtype; - pdf_jsimp_type *fieldtype; - pdf_jsimp_type *apptype; + js_State *imp; }; -static pdf_jsimp_obj *app_alert(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static void rethrow(pdf_js *js) { - pdf_js *js = (pdf_js *)jsctx; - fz_context *ctx = js->ctx; - pdf_jsimp_obj *cMsg_obj = NULL; - pdf_jsimp_obj *nIcon_obj = NULL; - pdf_jsimp_obj *nType_obj = NULL; - pdf_jsimp_obj *cTitle_obj = NULL; - pdf_jsimp_obj *nButton_obj = NULL; - pdf_alert_event event; - int arg_is_obj = 0; - - if (argc < 1 || argc > 6) - return NULL; + js_newerror(js->imp, fz_caught_message(js->ctx)); + js_throw(js->imp); +} - event.message = ""; - event.icon_type = PDF_ALERT_ICON_ERROR; - event.button_group_type = PDF_ALERT_BUTTON_GROUP_OK; - event.title = "MuPDF"; - event.check_box_message = NULL; - event.button_pressed = 0; - - fz_var(cMsg_obj); - fz_var(nIcon_obj); - fz_var(nType_obj); - fz_var(cTitle_obj); - fz_try(ctx) +/* Unpack argument object with named arguments into actual parameters. */ +static pdf_js *arguments(js_State *J, ...) +{ + if (js_isobject(J, 1)) { - arg_is_obj = (argc == 1 && pdf_jsimp_to_type(js->imp, args[0]) != JS_TYPE_STRING); - if (arg_is_obj) - { - cMsg_obj = pdf_jsimp_property(js->imp, args[0], "cMsg"); - nIcon_obj = pdf_jsimp_property(js->imp, args[0], "nIcon"); - nType_obj = pdf_jsimp_property(js->imp, args[0], "nType"); - cTitle_obj = pdf_jsimp_property(js->imp, args[0], "cTitle"); - } - else - { - switch (argc) - { - case 6: - case 5: - case 4: - cTitle_obj = args[3]; - case 3: - nType_obj = args[2]; - case 2: - nIcon_obj = args[1]; - case 1: - cMsg_obj = args[0]; - } - } - - if (cMsg_obj) - event.message = pdf_jsimp_to_string(js->imp, cMsg_obj); - - if (nIcon_obj) - event.icon_type = (int)pdf_jsimp_to_number(js->imp, nIcon_obj); + int i = 1; + va_list args; - if (nType_obj) - event.button_group_type = (int)pdf_jsimp_to_number(js->imp, nType_obj); + js_copy(J, 1); - if (cTitle_obj) - event.title = pdf_jsimp_to_string(js->imp, cTitle_obj); - - pdf_event_issue_alert(ctx, js->doc, &event); - nButton_obj = pdf_jsimp_from_number(js->imp, (double)event.button_pressed); - } - fz_always(ctx) - { - if (arg_is_obj) + va_start(args, J); + for (;;) { - pdf_jsimp_drop_obj(js->imp, cMsg_obj); - pdf_jsimp_drop_obj(js->imp, nIcon_obj); - pdf_jsimp_drop_obj(js->imp, nType_obj); - pdf_jsimp_drop_obj(js->imp, cTitle_obj); + const char *s = va_arg(args, const char *); + if (!s) + break; + js_getproperty(J, -1, s); + js_replace(J, i++); } - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } - - return nButton_obj; -} - -static pdf_jsimp_obj *app_execDialog(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) -{ - pdf_js *js = (pdf_js *)jsctx; + va_end(args); - pdf_event_issue_exec_dialog(js->ctx, js->doc); - - return NULL; + js_pop(J, 1); + } + return js_getcontext(J); } -static pdf_jsimp_obj *app_execMenuItem(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static char *pdf_from_utf8(fz_context *ctx, const char *utf8) { - pdf_js *js = (pdf_js *)jsctx; + char *pdf = fz_malloc(ctx, strlen(utf8)+1); + int i = 0; + unsigned char c; - if (argc == 1) - pdf_event_issue_exec_menu_item(js->ctx, js->doc, pdf_jsimp_to_string(js->imp, args[0])); + while ((c = *utf8) != 0) + { + if ((c & 0x80) == 0 && pdf_doc_encoding[c] == c) + { + pdf[i++] = c; + utf8++ ; + } + else + { + int rune; + int j; - return NULL; -} + utf8 += fz_chartorune(&rune, utf8); -static pdf_jsimp_obj *app_launchURL(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) -{ - pdf_js *js = (pdf_js *)jsctx; - char *cUrl; - int bNewFrame = 0; + for (j = 0; j < sizeof(pdf_doc_encoding) && pdf_doc_encoding[j] != rune; j++) + ; - switch (argc) - { - default: - return NULL; - case 2: - bNewFrame = (int)pdf_jsimp_to_number(js->imp, args[1]); - case 1: - cUrl = pdf_jsimp_to_string(js->imp, args[0]); + if (j < sizeof(pdf_doc_encoding)) + pdf[i++] = j; + } } - pdf_event_issue_launch_url(js->ctx, js->doc, cUrl, bNewFrame); + pdf[i] = 0; - return NULL; + return pdf; } -static pdf_obj *load_color(fz_context *ctx, pdf_document *doc, pdf_jsimp *imp, pdf_jsimp_obj *val) +static void app_alert(js_State *J) { - pdf_obj *col = NULL; - pdf_obj *comp = NULL; - pdf_jsimp_obj *jscomp = NULL; - int i; - int n; - - n = pdf_jsimp_array_len(imp, val); - - /* The only legitimate color expressed as an array of length 1 - * is [T], meaning transparent. Return a NULL object to represent - * transparent */ - if (n <= 1) - return NULL; + pdf_js *js = arguments(J, "cMsg", "nIcon", "nType", "cTitle", 0); + pdf_alert_event event; - col = pdf_new_array(ctx, doc, n-1); + event.message = js_tostring(J, 1); + event.icon_type = js_tointeger(J, 2); + event.button_group_type = js_tointeger(J, 3); + event.title = js_tostring(J, 4); - fz_var(comp); - fz_var(jscomp); - fz_try(ctx) - { - for (i = 0; i < n-1; i++) - { - jscomp = pdf_jsimp_array_item(imp, val, i+1); - comp = pdf_new_real(ctx, doc, pdf_jsimp_to_number(imp, jscomp)); - pdf_array_push(ctx, col, comp); - pdf_jsimp_drop_obj(imp, jscomp); - jscomp = NULL; - pdf_drop_obj(ctx, comp); - comp = NULL; - } - } - fz_catch(ctx) - { - pdf_jsimp_drop_obj(imp, jscomp); - pdf_drop_obj(ctx, comp); - pdf_drop_obj(ctx, col); - fz_rethrow(ctx); - } + fz_try(js->ctx) + pdf_event_issue_alert(js->ctx, js->doc, &event); + fz_catch(js->ctx) + rethrow(js); - return col; + js_pushnumber(J, event.button_pressed); } -static pdf_jsimp_obj *field_buttonSetCaption(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static void app_execDialog(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - char *name; - - if (argc != 1) - return NULL; + pdf_js *js = js_getcontext(J); + // monitor + // inheritDialog + // parentDoc - name = pdf_jsimp_to_string(js->imp, args[0]); - pdf_field_set_button_caption(js->ctx, js->doc, field, name); + fz_try(js->ctx) + pdf_event_issue_exec_dialog(js->ctx, js->doc); + fz_catch(js->ctx) + rethrow(js); - return NULL; + // return "ok" or "cancel" + js_pushstring(J, "cancel"); } -static pdf_jsimp_obj *field_getName(void *jsctx, void *obj) +static void app_execMenuItem(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_context *ctx = js->ctx; - pdf_obj *field = (pdf_obj *)obj; - char *name; - pdf_jsimp_obj *oname = NULL; - - if (field == NULL) - return NULL; - - name = pdf_field_name(ctx, js->doc, field); - fz_try(ctx) - { - oname = pdf_jsimp_from_string(js->imp, name); - } - fz_always(ctx) - { - fz_free(ctx, name); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } - - return oname; + pdf_js *js = js_getcontext(J); + const char *cMenuItem = js_tostring(J, 1); + fz_try(js->ctx) + pdf_event_issue_exec_menu_item(js->ctx, js->doc, cMenuItem); + fz_catch(js->ctx) + rethrow(js); } -static void field_setName(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void app_launchURL(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_warn(js->ctx, "Unexpected call to field_setName"); + pdf_js *js = js_getcontext(J); + const char *cUrl = js_tostring(J, 1); + int bNewFrame = js_toboolean(J, 1); + fz_try(js->ctx) + pdf_event_issue_launch_url(js->ctx, js->doc, cUrl, bNewFrame); + fz_catch(js->ctx) + rethrow(js); } -static pdf_jsimp_obj *field_getDisplay(void *jsctx, void *obj) +static void field_finalize(js_State *J, void *p) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - - return field ? pdf_jsimp_from_number(js->imp, (double)pdf_field_display(js->ctx, js->doc, field)) : NULL; + pdf_js *js = js_getcontext(J); + pdf_drop_obj(js->ctx, p); } -static void field_setDisplay(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void field_buttonSetCaption(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - if (field) - pdf_field_set_display(js->ctx, js->doc, field, (int)pdf_jsimp_to_number(js->imp, val)); + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + const char *cCaption = js_tostring(J, 1); + char *caption = pdf_from_utf8(js->ctx, cCaption); + fz_try(js->ctx) + pdf_field_set_button_caption(js->ctx, js->doc, field, caption); + fz_always(js->ctx) + fz_free(js->ctx, caption); + fz_catch(js->ctx) + rethrow(js); } -static pdf_jsimp_obj *field_getFillColor(void *jsctx, void *obj) +static void field_getName(js_State *J) { - return NULL; + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + char *name; + fz_try(js->ctx) + name = pdf_field_name(js->ctx, js->doc, field); + fz_catch(js->ctx) + rethrow(js); + js_pushstring(J, name); /* to utf8? */ } -static void field_setFillColor(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void field_setName(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_context *ctx = js->ctx; - pdf_obj *field = (pdf_obj *)obj; - pdf_obj *col; - - if (!field) - return; + pdf_js *js = js_getcontext(J); + fz_warn(js->ctx, "Unexpected call to field_setName"); +} - col = load_color(ctx, js->doc, js->imp, val); - fz_try(ctx) - { - pdf_field_set_fill_color(ctx, js->doc, field, col); - } - fz_always(ctx) - { - pdf_drop_obj(ctx, col); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } +static void field_getDisplay(js_State *J) +{ + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + int display; + fz_try(js->ctx) + display = pdf_field_display(js->ctx, js->doc, field); + fz_catch(js->ctx) + rethrow(js); + js_pushnumber(J, display); } -static pdf_jsimp_obj *field_getTextColor(void *jsctx, void *obj) +static void field_setDisplay(js_State *J) { - return NULL; + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + int display = js_tonumber(J, 1); + fz_try(js->ctx) + pdf_field_set_display(js->ctx, js->doc, field, display); + fz_catch(js->ctx) + rethrow(js); } -static void field_setTextColor(void *jsctx, void *obj, pdf_jsimp_obj *val) +static pdf_obj *load_color(pdf_js *js, int idx) { - pdf_js *js = (pdf_js *)jsctx; fz_context *ctx = js->ctx; - pdf_obj *field = (pdf_obj *)obj; - pdf_obj *col; + pdf_document *doc = js->doc; + js_State *J = js->imp; + + pdf_obj *color = NULL; + int i, n; + float c; + + n = js_getlength(J, idx); + + /* The only legitimate color expressed as an array of length 1 + * is [T], meaning transparent. Return a NULL object to represent + * transparent */ + if (n <= 1) + return NULL; - if (!field) - return; + fz_var(color); - col = load_color(ctx, js->doc, js->imp, val); fz_try(ctx) { - pdf_field_set_text_color(ctx, js->doc, field, col); - } - fz_always(ctx) - { - pdf_drop_obj(ctx, col); + color = pdf_new_array(ctx, doc, n-1); + for (i = 0; i < n-1; i++) + { + js_getindex(J, idx, i+1); + c = js_tonumber(J, -1); + js_pop(J, 1); + + pdf_array_push_drop(ctx, color, pdf_new_real(ctx, doc, c)); + } } fz_catch(ctx) { - fz_rethrow(ctx); + pdf_drop_obj(ctx, color); + rethrow(js); } + + return color; } -static pdf_jsimp_obj *field_getBorderStyle(void *jsctx, void *obj) +static void field_getFillColor(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - - return field ? pdf_jsimp_from_string(js->imp, pdf_field_border_style(js->ctx, js->doc, field)) : NULL; + js_pushundefined(J); } -static void field_setBorderStyle(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void field_setFillColor(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - - if (field) - pdf_field_set_border_style(js->ctx, js->doc, field, pdf_jsimp_to_string(js->imp, val)); + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + pdf_obj *color = load_color(js, 1); + fz_try(js->ctx) + pdf_field_set_fill_color(js->ctx, js->doc, field, color); + fz_always(js->ctx) + pdf_drop_obj(js->ctx, color); + fz_catch(js->ctx) + rethrow(js); } -static pdf_jsimp_obj *field_getValue(void *jsctx, void *obj) +static void field_getTextColor(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - char *fval; - - if (!field) - return NULL; - - fval = pdf_field_value(js->ctx, js->doc, field); - /* TODO: free fval! */ - return pdf_jsimp_from_string(js->imp, fval?fval:""); + js_pushundefined(J); } -static void field_setValue(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void field_setTextColor(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - pdf_obj *field = (pdf_obj *)obj; - - if (field) - (void)pdf_field_set_value(js->ctx, js->doc, field, pdf_jsimp_to_string(js->imp, val)); + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + pdf_obj *color = load_color(js, 1); + fz_try(js->ctx) + pdf_field_set_text_color(js->ctx, js->doc, field, color); + fz_always(js->ctx) + pdf_drop_obj(js->ctx, color); + fz_catch(js->ctx) + rethrow(js); } -static pdf_jsimp_obj *event_getTarget(void *jsctx, void *obj) +static void field_getBorderStyle(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - - return pdf_jsimp_new_obj(js->imp, js->fieldtype, js->event.target); + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + const char *border_style; + fz_try(js->ctx) + border_style = pdf_field_border_style(js->ctx, js->doc, field); + fz_catch(js->ctx) + rethrow(js); + js_pushstring(J, border_style); } -static void event_setTarget(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void field_setBorderStyle(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_warn(js->ctx, "Unexpected call to event_setTarget"); + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + const char *border_style = js_tostring(J, 1); + fz_try(js->ctx) + pdf_field_set_border_style(js->ctx, js->doc, field, border_style); + fz_catch(js->ctx) + rethrow(js); } -static pdf_jsimp_obj *event_getValue(void *jsctx, void *obj) +static void field_getValue(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - char *v = js->event.value; + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + char *val; - return pdf_jsimp_from_string(js->imp, v?v:""); -} + fz_try(js->ctx) + val = pdf_field_value(js->ctx, js->doc, field); + fz_catch(js->ctx) + rethrow(js); -static void event_setValue(void *jsctx, void *obj, pdf_jsimp_obj *val) -{ - pdf_js *js = (pdf_js *)jsctx; - fz_context *ctx = js->ctx; - fz_free(ctx, js->event.value); - js->event.value = NULL; - js->event.value = fz_strdup(ctx, pdf_jsimp_to_string(js->imp, val)); + js_pushstring(J, val ? val : ""); + + fz_free(js->ctx, val); } -static pdf_jsimp_obj *event_getWillCommit(void *jsctx, void *obj) +static void field_setValue(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; + pdf_js *js = js_getcontext(J); + pdf_obj *field = js_touserdata(J, 0, "Field"); + const char *value = js_tostring(J, 1); - return pdf_jsimp_from_number(js->imp, 1.0); + fz_try(js->ctx) + (void)pdf_field_set_value(js->ctx, js->doc, field, value); + fz_catch(js->ctx) + rethrow(js); } -static void event_setWillCommit(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void event_getTarget(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_warn(js->ctx, "Unexpected call to event_setWillCommit"); + pdf_js *js = js_getcontext(J); + js_getregistry(J, "Field"); + js_newuserdata(J, "Field", pdf_keep_obj(js->ctx, js->event.target), field_finalize); } -static pdf_jsimp_obj *event_getRC(void *jsctx, void *obj) +static void event_setTarget(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - - return pdf_jsimp_from_number(js->imp, (double)js->event.rc); + pdf_js *js = js_getcontext(J); + fz_warn(js->ctx, "Unexpected call to event_setTarget"); } -static void event_setRC(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void event_getValue(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - - js->event.rc = (int)pdf_jsimp_to_number(js->imp, val); + pdf_js *js = js_getcontext(J); + const char *v = js->event.value; + js_pushstring(J, v ? v : ""); } -static pdf_jsimp_obj *doc_getEvent(void *jsctx, void *obj) +static void event_setValue(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - - return pdf_jsimp_new_obj(js->imp, js->eventtype, &js->event); + pdf_js *js = js_getcontext(J); + const char *value = js_tostring(J, 1); + fz_free(js->ctx, js->event.value); + js->event.value = fz_strdup(js->ctx, value); } -static void doc_setEvent(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void event_getWillCommit(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_warn(js->ctx, "Unexpected call to doc_setEvent"); + js_pushnumber(J, 1); } -static pdf_jsimp_obj *doc_getApp(void *jsctx, void *obj) +static void event_setWillCommit(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - - return pdf_jsimp_new_obj(js->imp, js->apptype, NULL); + pdf_js *js = js_getcontext(J); + fz_warn(js->ctx, "Unexpected call to event_setWillCommit"); } -static void doc_setApp(void *jsctx, void *obj, pdf_jsimp_obj *val) +static void event_getRC(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_warn(js->ctx, "Unexpected call to doc_setApp"); + pdf_js *js = js_getcontext(J); + js_pushnumber(J, js->event.rc); } -static char *utf8_to_pdf(fz_context *ctx, char *utf8) +static void event_setRC(js_State *J) { - char *pdf = fz_malloc(ctx, strlen(utf8)+1); - int i = 0; - unsigned char c; - - while ((c = *utf8) != 0) - { - if ((c & 0x80) == 0 && pdf_doc_encoding[c] == c) - { - pdf[i++] = c; - utf8++ ; - } - else - { - int rune; - int j; - - utf8 += fz_chartorune(&rune, utf8); - - for (j = 0; j < sizeof(pdf_doc_encoding) && pdf_doc_encoding[j] != rune; j++) - ; - - if (j < sizeof(pdf_doc_encoding)) - pdf[i++] = j; - } - } - - pdf[i] = 0; - - return pdf; + pdf_js *js = js_getcontext(J); + js->event.rc = js_tointeger(js->imp, 1); } -static pdf_jsimp_obj *doc_getField(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static void doc_getField(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; + pdf_js *js = js_getcontext(J); fz_context *ctx = js->ctx; - pdf_obj *dict = NULL; - char *utf8; - char *name = NULL; - - if (argc != 1) - return NULL; + const char *cName = js_tostring(J, 1); + char *name = pdf_from_utf8(ctx, cName); + pdf_obj *dict; - fz_var(dict); - fz_var(name); fz_try(ctx) - { - utf8 = pdf_jsimp_to_string(js->imp, args[0]); - - if (utf8) - { - name = utf8_to_pdf(ctx, utf8); - dict = pdf_lookup_field(js->ctx, js->form, name); - } - } + dict = pdf_lookup_field(ctx, js->form, name); fz_always(ctx) - { fz_free(ctx, name); - } fz_catch(ctx) + rethrow(js); + + if (dict) { - fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); - fz_warn(ctx, "doc_getField failed: %s", fz_caught_message(ctx)); - dict = NULL; + js_getregistry(J, "Field"); + js_newuserdata(J, "Field", pdf_keep_obj(js->ctx, dict), field_finalize); + } + else + { + js_pushnull(J); } - - return dict ? pdf_jsimp_new_obj(js->imp, js->fieldtype, dict) : NULL; } -static void reset_field(pdf_js *js, pdf_jsimp_obj *item) +static void reset_field(pdf_js *js, const char *cName) { fz_context *ctx = js->ctx; - char *name = NULL; - char *utf8 = pdf_jsimp_to_string(js->imp, item); - - if (utf8) + if (cName) { - pdf_obj *field; - - fz_var(name); + char *name = pdf_from_utf8(ctx, cName); fz_try(ctx) { - name = utf8_to_pdf(ctx, utf8); - field = pdf_lookup_field(js->ctx, js->form, name); + pdf_obj *field = js_touserdata(js->imp, 0, "Field"); if (field) - pdf_field_reset(js->ctx, js->doc, field); + pdf_field_reset(ctx, js->doc, field); } fz_always(ctx) - { fz_free(ctx, name); - } fz_catch(ctx) - { - fz_rethrow(ctx); - } + rethrow(js); } } -static pdf_jsimp_obj *doc_resetForm(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static void doc_resetForm(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; + pdf_js *js = js_getcontext(J); fz_context *ctx = js->ctx; - pdf_jsimp_obj *arr = NULL; - pdf_jsimp_obj *elem = NULL; + int i, n; - switch (argc) + /* An array of fields has been passed in. Call pdf_reset_field on each item. */ + if (js_isarray(J, 1)) { - case 0: - break; - case 1: - switch (pdf_jsimp_to_type(js->imp, args[0])) + n = js_getlength(J, 1); + for (i = 0; i < n; ++i) { - case JS_TYPE_NULL: - break; - case JS_TYPE_ARRAY: - arr = args[0]; - break; - case JS_TYPE_STRING: - elem = args[0]; - break; - default: - return NULL; + js_getindex(J, 1, i); + reset_field(js, js_tostring(J, -1)); + js_pop(J, 1); } - break; - default: - return NULL; } - fz_try(ctx) + /* No argument or null passed in means reset all. */ + else { - if(arr) + n = pdf_array_len(ctx, js->form); + for (i = 0; i < n; i++) { - /* An array of fields has been passed in. Call - * pdf_reset_field on each */ - int i, n = pdf_jsimp_array_len(js->imp, arr); - - for (i = 0; i < n; i++) - { - pdf_jsimp_obj *item = pdf_jsimp_array_item(js->imp, arr, i); - - if (item) - reset_field(js, item); - - } - } - else if (elem) - { - reset_field(js, elem); - } - else - { - /* No argument or null passed in means reset all. */ - int i, n = pdf_array_len(ctx, js->form); - - for (i = 0; i < n; i++) - pdf_field_reset(js->ctx, js->doc, pdf_array_get(ctx, js->form, i)); + fz_try(ctx) + pdf_field_reset(ctx, js->doc, pdf_array_get(ctx, js->form, i)); + fz_catch(ctx) + rethrow(js); } } - fz_catch(ctx) - { - fz_warn(ctx, "doc_resetForm failed: %s", fz_caught_message(ctx)); - } - - return NULL; } -static pdf_jsimp_obj *doc_print(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static void doc_print(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - - pdf_event_issue_print(js->ctx, js->doc); - - return NULL; + pdf_js *js = js_getcontext(J); + fz_try(js->ctx) + pdf_event_issue_print(js->ctx, js->doc); + fz_catch(js->ctx) + rethrow(js); } -static pdf_jsimp_obj *doc_mailDoc(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) +static void doc_mailDoc(js_State *J) { - pdf_js *js = (pdf_js *)jsctx; - fz_context *ctx = js->ctx; - pdf_jsimp_obj *bUI_obj = NULL; - pdf_jsimp_obj *cTo_obj = NULL; - pdf_jsimp_obj *cCc_obj = NULL; - pdf_jsimp_obj *cBcc_obj = NULL; - pdf_jsimp_obj *cSubject_obj = NULL; - pdf_jsimp_obj *cMessage_obj = NULL; + pdf_js *js = arguments(J, "bUI", "cTo", "cCc", "cBcc", "cSubject", "cMessage", 0); pdf_mail_doc_event event; - int arg_is_obj = 0; - if (argc < 1 || argc > 6) - return NULL; + event.ask_user = js_isdefined(J, 1) ? js_toboolean(J, 1) : 1; + event.to = js_tostring(J, 2); + event.cc = js_tostring(J, 3); + event.bcc = js_tostring(J, 4); + event.subject = js_tostring(J, 5); + event.message = js_tostring(J, 6); - event.ask_user = 1; - event.to = ""; - event.cc = ""; - event.bcc = ""; - event.subject = ""; - event.message = ""; - - fz_var(bUI_obj); - fz_var(cTo_obj); - fz_var(cCc_obj); - fz_var(cBcc_obj); - fz_var(cSubject_obj); - fz_var(cMessage_obj); - fz_try(ctx) - { - arg_is_obj = (argc == 1 && pdf_jsimp_to_type(js->imp, args[0]) != JS_TYPE_BOOLEAN); - if (arg_is_obj) - { - bUI_obj = pdf_jsimp_property(js->imp, args[0], "bUI"); - cTo_obj = pdf_jsimp_property(js->imp, args[0], "cTo"); - cCc_obj = pdf_jsimp_property(js->imp, args[0], "cCc"); - cBcc_obj = pdf_jsimp_property(js->imp, args[0], "cBcc"); - cSubject_obj = pdf_jsimp_property(js->imp, args[0], "cSubject"); - cMessage_obj = pdf_jsimp_property(js->imp, args[0], "cMessage"); - } - else - { - switch (argc) - { - case 6: - cMessage_obj = args[5]; - case 5: - cSubject_obj = args[4]; - case 4: - cBcc_obj = args[3]; - case 3: - cCc_obj = args[2]; - case 2: - cTo_obj = args[1]; - case 1: - bUI_obj = args[0]; - } - } - - if (bUI_obj) - event.ask_user = (int)pdf_jsimp_to_number(js->imp, bUI_obj); - - if (cTo_obj) - event.to = pdf_jsimp_to_string(js->imp, cTo_obj); + fz_try(js->ctx) + pdf_event_issue_mail_doc(js->ctx, js->doc, &event); + fz_catch(js->ctx) + rethrow(js); +} - if (cCc_obj) - event.cc = pdf_jsimp_to_string(js->imp, cCc_obj); +static void addmethod(js_State *J, const char *name, js_CFunction fun, int n) +{ + const char *realname = strchr(name, '.'); + realname = realname ? realname + 1 : name; + js_newcfunction(J, fun, name, n); + js_defproperty(J, -2, realname, JS_READONLY | JS_DONTENUM | JS_DONTCONF); +} - if (cBcc_obj) - event.bcc = pdf_jsimp_to_string(js->imp, cBcc_obj); +static void addproperty(js_State *J, const char *name, js_CFunction getfun, js_CFunction setfun) +{ + const char *realname = strchr(name, '.'); + realname = realname ? realname + 1 : name; + js_newcfunction(J, getfun, name, 0); + js_newcfunction(J, setfun, name, 1); + js_defaccessor(J, -3, realname, JS_READONLY | JS_DONTENUM | JS_DONTCONF); +} - if (cSubject_obj) - event.subject = pdf_jsimp_to_string(js->imp, cSubject_obj); +static void declare_dom(pdf_js *js) +{ + js_State *J = js->imp; - if (cMessage_obj) - event.message = pdf_jsimp_to_string(js->imp, cMessage_obj); + /* Allow access to the global environment via the 'global' name */ + js_pushglobal(J); + js_defglobal(J, "global", JS_READONLY | JS_DONTCONF | JS_DONTENUM); - pdf_event_issue_mail_doc(js->ctx, js->doc, &event); - } - fz_always(ctx) + /* Create the 'app' object */ + js_newobject(J); { - if (arg_is_obj) - { - pdf_jsimp_drop_obj(js->imp, bUI_obj); - pdf_jsimp_drop_obj(js->imp, cTo_obj); - pdf_jsimp_drop_obj(js->imp, cCc_obj); - pdf_jsimp_drop_obj(js->imp, cBcc_obj); - pdf_jsimp_drop_obj(js->imp, cSubject_obj); - pdf_jsimp_drop_obj(js->imp, cMessage_obj); - } + addmethod(J, "app.alert", app_alert, 4); + addmethod(J, "app.execDialog", app_execDialog, 0); + addmethod(J, "app.execMenuItem", app_execMenuItem, 1); + addmethod(J, "app.launchURL", app_launchURL, 2); } - fz_catch(ctx) + js_defglobal(J, "app", JS_READONLY | JS_DONTCONF | JS_DONTENUM); + + /* Create the 'event' object */ + js_newobject(J); { - fz_rethrow(ctx); + addproperty(J, "event.target", event_getTarget, event_setTarget); + addproperty(J, "event.value", event_getValue, event_setValue); + addproperty(J, "event.willCommit", event_getWillCommit, event_setWillCommit); + addproperty(J, "event.rc", event_getRC, event_setRC); } + js_defglobal(J, "event", JS_READONLY | JS_DONTCONF | JS_DONTENUM); - return NULL; -} + /* Create the Field prototype object */ + js_newobject(J); + { + addproperty(J, "Field.value", field_getValue, field_setValue); + addproperty(J, "Field.borderStyle", field_getBorderStyle, field_setBorderStyle); + addproperty(J, "Field.textColor", field_getTextColor, field_setTextColor); + addproperty(J, "Field.fillColor", field_getFillColor, field_setFillColor); + addproperty(J, "Field.display", field_getDisplay, field_setDisplay); + addproperty(J, "Field.name", field_getName, field_setName); + addmethod(J, "Field.buttonSetCaption", field_buttonSetCaption, 1); + } + js_setregistry(J, "Field"); -static void declare_dom(pdf_js *js) -{ - pdf_jsimp *imp = js->imp; - - /* Create the document type */ - js->doctype = pdf_jsimp_new_type(imp, NULL, "Document"); - pdf_jsimp_addmethod(imp, js->doctype, "getField", doc_getField); - pdf_jsimp_addmethod(imp, js->doctype, "resetForm", doc_resetForm); - pdf_jsimp_addmethod(imp, js->doctype, "print", doc_print); - pdf_jsimp_addmethod(imp, js->doctype, "mailDoc", doc_mailDoc); - pdf_jsimp_addproperty(imp, js->doctype, "event", doc_getEvent, doc_setEvent); - pdf_jsimp_addproperty(imp, js->doctype, "app", doc_getApp, doc_setApp); - - /* Create the event type */ - js->eventtype = pdf_jsimp_new_type(imp, NULL, "Event"); - pdf_jsimp_addproperty(imp, js->eventtype, "target", event_getTarget, event_setTarget); - pdf_jsimp_addproperty(imp, js->eventtype, "value", event_getValue, event_setValue); - pdf_jsimp_addproperty(imp, js->eventtype, "willCommit", event_getWillCommit, event_setWillCommit); - pdf_jsimp_addproperty(imp, js->eventtype, "rc", event_getRC, event_setRC); - - /* Create the field type */ - js->fieldtype = pdf_jsimp_new_type(imp, NULL, "Field"); - pdf_jsimp_addproperty(imp, js->fieldtype, "value", field_getValue, field_setValue); - pdf_jsimp_addproperty(imp, js->fieldtype, "borderStyle", field_getBorderStyle, field_setBorderStyle); - pdf_jsimp_addproperty(imp, js->fieldtype, "textColor", field_getTextColor, field_setTextColor); - pdf_jsimp_addproperty(imp, js->fieldtype, "fillColor", field_getFillColor, field_setFillColor); - pdf_jsimp_addproperty(imp, js->fieldtype, "display", field_getDisplay, field_setDisplay); - pdf_jsimp_addproperty(imp, js->fieldtype, "name", field_getName, field_setName); - pdf_jsimp_addmethod(imp, js->fieldtype, "buttonSetCaption", field_buttonSetCaption); - - /* Create the app type */ - js->apptype = pdf_jsimp_new_type(imp, NULL, "Application"); - pdf_jsimp_addmethod(imp, js->apptype, "alert", app_alert); - pdf_jsimp_addmethod(imp, js->apptype, "execDialog", app_execDialog); - pdf_jsimp_addmethod(imp, js->apptype, "execMenuItem", app_execMenuItem); - pdf_jsimp_addmethod(imp, js->apptype, "launchURL", app_launchURL); - - /* Create the document object and tell the engine to use */ - pdf_jsimp_set_global_type(js->imp, js->doctype); + /* Create the Doc prototype object */ + js_newobject(J); + { + addmethod(J, "Doc.getField", doc_getField, 1); + addmethod(J, "Doc.resetForm", doc_resetForm, 0); + addmethod(J, "Doc.print", doc_print, 0); + addmethod(J, "Doc.mailDoc", doc_mailDoc, 6); + } + js_setregistry(J, "Doc"); } static void preload_helpers(pdf_js *js) @@ -759,7 +551,7 @@ static void preload_helpers(pdf_js *js) * Return a fixed number from Math.random(). */ #ifdef CLUSTER - pdf_jsimp_execute(js->imp, + js_dostring(js->imp, "var MuPDFOldDate = Date\n" "Date = function() { return new MuPDFOldDate(298252800000); }\n" "Date.now = function() { return 298252800000; }\n" @@ -769,55 +561,63 @@ static void preload_helpers(pdf_js *js) ); #endif - pdf_jsimp_execute(js->imp, + js_dostring(js->imp, #include "gen_js_util.h" ); } -static void pdf_drop_js(pdf_js *js) +void pdf_drop_js(fz_context *ctx, pdf_js *js) { if (js) { - fz_context *ctx = js->ctx; + js_freestate(js->imp); fz_free(ctx, js->event.value); - pdf_jsimp_drop_type(js->imp, js->apptype); - pdf_jsimp_drop_type(js->imp, js->eventtype); - pdf_jsimp_drop_type(js->imp, js->fieldtype); - pdf_jsimp_drop_type(js->imp, js->doctype); - pdf_drop_jsimp(js->imp); fz_free(ctx, js); } } +static void *pdf_js_alloc(void *actx, void *ptr, unsigned int n) +{ + fz_context *ctx = actx; + if (n == 0) { + fz_free(ctx, ptr); + return NULL; + } + if (ptr) + return fz_resize_array(ctx, ptr, n, 1); + return fz_malloc_array(ctx, n, 1); +} + static pdf_js *pdf_new_js(fz_context *ctx, pdf_document *doc) { - pdf_js *js = NULL; + pdf_js *js = fz_malloc_struct(ctx, pdf_js); + + js->ctx = ctx; + js->doc = doc; - fz_var(js); fz_try(ctx) { pdf_obj *root, *acroform; - js = fz_malloc_struct(ctx, pdf_js); - js->ctx = ctx; - js->doc = doc; - /* Find the form array */ root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root); acroform = pdf_dict_get(ctx, root, PDF_NAME_AcroForm); js->form = pdf_dict_get(ctx, acroform, PDF_NAME_Fields); - /* Initialise the javascript engine, passing the main context - * for use in memory allocation and exception handling. Also - * pass our js context, for it to pass back to us. */ - js->imp = pdf_new_jsimp(ctx, js); - declare_dom(js); + /* Initialise the javascript engine, passing the fz_context for use in memory allocation. */ + js->imp = js_newstate(pdf_js_alloc, ctx, 0); + if (!js->imp) + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot initialize javascript engine"); + + /* Also set our pdf_js context, so we can retrieve it in callbacks. */ + js_setcontext(js->imp, js); + declare_dom(js); preload_helpers(js); } fz_catch(ctx) { - pdf_drop_js(js); + pdf_drop_js(ctx, js); js = NULL; } @@ -826,51 +626,29 @@ static pdf_js *pdf_new_js(fz_context *ctx, pdf_document *doc) static void pdf_js_load_document_level(pdf_js *js) { - pdf_document *doc = js->doc; fz_context *ctx = js->ctx; - pdf_obj *javascript = NULL; - char *codebuf = NULL; + pdf_document *doc = js->doc; + pdf_obj *javascript; + int len, i; + + javascript = pdf_load_name_tree(ctx, doc, PDF_NAME_JavaScript); + len = pdf_dict_len(ctx, javascript); - fz_var(javascript); - fz_var(codebuf); fz_try(ctx) { - int len, i; - - javascript = pdf_load_name_tree(ctx, doc, PDF_NAME_JavaScript); - len = pdf_dict_len(ctx, javascript); - for (i = 0; i < len; i++) { pdf_obj *fragment = pdf_dict_get_val(ctx, javascript, i); pdf_obj *code = pdf_dict_get(ctx, fragment, PDF_NAME_JS); - - fz_var(codebuf); - fz_try(ctx) - { - codebuf = pdf_to_utf8(ctx, doc, code); - pdf_jsimp_execute(js->imp, codebuf); - } - fz_always(ctx) - { - fz_free(ctx, codebuf); - codebuf = NULL; - } - fz_catch(ctx) - { - fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); - fz_warn(ctx, "Warning: %s", fz_caught_message(ctx)); - } + char *codebuf = pdf_to_utf8(ctx, doc, code); + pdf_js_execute(js, codebuf); + fz_free(ctx, codebuf); } } fz_always(ctx) - { pdf_drop_obj(ctx, javascript); - } fz_catch(ctx) - { fz_rethrow(ctx); - } } void pdf_js_setup_event(pdf_js *js, pdf_js_event *e) @@ -894,41 +672,24 @@ pdf_js_event *pdf_js_get_event(pdf_js *js) return js ? &js->event : NULL; } -void pdf_js_execute(pdf_js *js, char *code) -{ - if (js) - { - fz_context *ctx = js->ctx; - fz_try(ctx) - { - pdf_jsimp_execute(js->imp, code); - } - fz_catch(ctx) - { - } - } -} - -void pdf_js_execute_count(pdf_js *js, char *code, int count) +void pdf_js_execute(pdf_js *js, char *source) { if (js) { - fz_context *ctx = js->ctx; - fz_try(ctx) - { - pdf_jsimp_execute_count(js->imp, code, count); - } - fz_catch(ctx) - { - } + puts(source); + if (js_ploadstring(js->imp, "[pdf]", source)) + return; + js_getregistry(js->imp, "Doc"); /* set 'this' to the Doc object */ + js_pcall(js->imp, 0); + js_pop(js->imp, 1); } } void pdf_enable_js(fz_context *ctx, pdf_document *doc) { - if (!doc->js) { + if (!doc->js) + { doc->js = pdf_new_js(ctx, doc); - doc->drop_js = pdf_drop_js; pdf_js_load_document_level(doc->js); } } @@ -936,7 +697,7 @@ void pdf_enable_js(fz_context *ctx, pdf_document *doc) void pdf_disable_js(fz_context *ctx, pdf_document *doc) { if (doc->js) - doc->drop_js(doc->js); + pdf_drop_js(ctx, doc->js); doc->js = NULL; } diff --git a/source/pdf/js/pdf-jsimp-cpp.c b/source/pdf/js/pdf-jsimp-cpp.c deleted file mode 100644 index a23c15f6..00000000 --- a/source/pdf/js/pdf-jsimp-cpp.c +++ /dev/null @@ -1,225 +0,0 @@ -/* This file contains wrapper functions for pdf_jsimp functions implemented - * in C++, from which calls to fz_throw aren't safe. The C++ versions - * return errors explicitly, and these wrappers then throw them. */ - -#include "mupdf/pdf.h" -#include "pdf-jsimp-cpp.h" - -pdf_jsimp *pdf_new_jsimp(fz_context *ctx, void *jsctx) -{ - pdf_jsimp *jsi = NULL; - const char *err = pdf_new_jsimp_cpp(ctx, jsctx, &jsi); - if (err != NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "%s", err); - - return jsi; -} - -void pdf_drop_jsimp(pdf_jsimp *imp) -{ - if (imp) - { - fz_context *ctx = pdf_jsimp_ctx_cpp(imp); - const char *err = pdf_drop_jsimp_cpp(imp); - if (err != NULL) - fz_warn(ctx, "%s", err); - } -} - -pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr, char *name) -{ - pdf_jsimp_type *type = NULL; - const char *err = pdf_jsimp_new_type_cpp(imp, dtr, &type); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return type; -} - -void pdf_jsimp_drop_type(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - const char *err = pdf_jsimp_drop_type_cpp(imp, type); - if (err != NULL) - fz_warn(pdf_jsimp_ctx_cpp(imp), "%s", err); -} - -void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) -{ - const char *err = pdf_jsimp_addmethod_cpp(imp, type, name, meth); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); -} - -void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) -{ - const char *err = pdf_jsimp_addproperty_cpp(imp, type, name, get, set); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); -} - -void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - const char *err = pdf_jsimp_set_global_type_cpp(imp, type); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); -} - -pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj) -{ - pdf_jsimp_obj *obj = NULL; - const char *err = pdf_jsimp_new_obj_cpp(imp, type, natobj, &obj); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return obj; -} - -void pdf_jsimp_drop_obj(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - const char *err = pdf_jsimp_drop_obj_cpp(imp, obj); - if (err != NULL) - fz_warn(pdf_jsimp_ctx_cpp(imp), "%s", err); -} - -int pdf_jsimp_to_type(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - int type = 0; - const char *err = pdf_jsimp_to_type_cpp(imp, obj, &type); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return type; -} - -pdf_jsimp_obj *pdf_jsimp_from_string(pdf_jsimp *imp, char *str) -{ - pdf_jsimp_obj *obj = NULL; - const char *err = pdf_jsimp_from_string_cpp(imp, str, &obj); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return obj; -} - -char *pdf_jsimp_to_string(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - char *str = NULL; - const char *err = pdf_jsimp_to_string_cpp(imp, obj, &str); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return str; -} - -pdf_jsimp_obj *pdf_jsimp_from_number(pdf_jsimp *imp, double num) -{ - pdf_jsimp_obj *obj = NULL; - const char *err = pdf_jsimp_from_number_cpp(imp, num, &obj); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return obj; -} - -double pdf_jsimp_to_number(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - double num; - const char *err = pdf_jsimp_to_number_cpp(imp, obj, &num); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return num; -} - -int pdf_jsimp_array_len(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - int len = 0; - const char *err = pdf_jsimp_array_len_cpp(imp, obj, &len); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return len; -} - -pdf_jsimp_obj *pdf_jsimp_array_item(pdf_jsimp *imp, pdf_jsimp_obj *obj, int i) -{ - pdf_jsimp_obj *item = NULL; - const char *err = pdf_jsimp_array_item_cpp(imp, obj, i, &item); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return item; -} - -pdf_jsimp_obj *pdf_jsimp_property(pdf_jsimp *imp, pdf_jsimp_obj *obj, char *prop) -{ - pdf_jsimp_obj *pobj = NULL; - const char *err = pdf_jsimp_property_cpp(imp, obj, prop, &pobj); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); - - return pobj; -} - -void pdf_jsimp_execute(pdf_jsimp *imp, char *code) -{ - const char *err = pdf_jsimp_execute_cpp(imp, code); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); -} - -void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count) -{ - const char *err = pdf_jsimp_execute_count_cpp(imp, code, count); - if (err != NULL) - fz_throw(pdf_jsimp_ctx_cpp(imp), FZ_ERROR_GENERIC, "%s", err); -} -pdf_jsimp_obj *pdf_jsimp_call_method(pdf_jsimp *imp, pdf_jsimp_method *meth, void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) -{ - fz_context *ctx = pdf_jsimp_ctx_cpp(imp); - pdf_jsimp_obj *res; - - fz_try(ctx) - { - res = meth(jsctx, obj, argc, args); - } - fz_catch(ctx) - { - res = NULL; - fz_warn(ctx, "%s", fz_caught_message(ctx)); - } - - return res; -} - -pdf_jsimp_obj *pdf_jsimp_call_getter(pdf_jsimp *imp, pdf_jsimp_getter *get, void *jsctx, void *obj) -{ - fz_context *ctx = pdf_jsimp_ctx_cpp(imp); - pdf_jsimp_obj *res; - - fz_try(ctx) - { - res = get(jsctx, obj); - } - fz_catch(ctx) - { - res = NULL; - fz_warn(ctx, "%s", fz_caught_message(ctx)); - } - - return res; -} - -void pdf_jsimp_call_setter(pdf_jsimp *imp, pdf_jsimp_setter *set, void *jsctx, void *obj, pdf_jsimp_obj *val) -{ - fz_context *ctx = pdf_jsimp_ctx_cpp(imp); - - fz_try(ctx) - { - set(jsctx, obj, val); - } - fz_catch(ctx) - { - fz_warn(ctx, "%s", fz_caught_message(ctx)); - } -} diff --git a/source/pdf/js/pdf-jsimp-cpp.h b/source/pdf/js/pdf-jsimp-cpp.h deleted file mode 100644 index 83af1d23..00000000 --- a/source/pdf/js/pdf-jsimp-cpp.h +++ /dev/null @@ -1,29 +0,0 @@ -/* C++ version of the pdf_jsimp api. C++ cannot safely call fz_throw, - * so C++ implementations return explicit errors in char * form. */ - -fz_context *pdf_jsimp_ctx_cpp(pdf_jsimp *imp); -const char *pdf_new_jsimp_cpp(fz_context *ctx, void *jsctx, pdf_jsimp **imp); -const char *pdf_drop_jsimp_cpp(pdf_jsimp *imp); -const char *pdf_jsimp_new_type_cpp(pdf_jsimp *imp, pdf_jsimp_dtr *dtr, pdf_jsimp_type **type); -const char *pdf_jsimp_drop_type_cpp(pdf_jsimp *imp, pdf_jsimp_type *type); -const char *pdf_jsimp_addmethod_cpp(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth); -const char *pdf_jsimp_addproperty_cpp(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set); -const char *pdf_jsimp_set_global_type_cpp(pdf_jsimp *imp, pdf_jsimp_type *type); -const char *pdf_jsimp_new_obj_cpp(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj, pdf_jsimp_obj **obj); -const char *pdf_jsimp_drop_obj_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj); -const char *pdf_jsimp_to_type_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, int *type); -const char *pdf_jsimp_from_string_cpp(pdf_jsimp *imp, char *str, pdf_jsimp_obj **obj); -const char *pdf_jsimp_to_string_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, char **str); -const char *pdf_jsimp_from_number_cpp(pdf_jsimp *imp, double num, pdf_jsimp_obj **obj); -const char *pdf_jsimp_to_number_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, double *num); -const char *pdf_jsimp_array_len_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, int *len); -const char *pdf_jsimp_array_item_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, int i, pdf_jsimp_obj **item); -const char *pdf_jsimp_property_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, char *prop, pdf_jsimp_obj **pobj); -const char *pdf_jsimp_execute_cpp(pdf_jsimp *imp, char *code); -const char *pdf_jsimp_execute_count_cpp(pdf_jsimp *imp, char *code, int count); - -/* Also when calling back into mupdf, all exceptions must be caught. The functions bellow - * wrap these calls */ -pdf_jsimp_obj *pdf_jsimp_call_method(pdf_jsimp *imp, pdf_jsimp_method *meth, void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]); -pdf_jsimp_obj *pdf_jsimp_call_getter(pdf_jsimp *imp, pdf_jsimp_getter *get, void *jsctx, void *obj); -void pdf_jsimp_call_setter(pdf_jsimp *imp, pdf_jsimp_setter *set, void *jsctx, void *obj, pdf_jsimp_obj *val); diff --git a/source/pdf/js/pdf-jsimp-jscore.c b/source/pdf/js/pdf-jsimp-jscore.c deleted file mode 100644 index 364b08b5..00000000 --- a/source/pdf/js/pdf-jsimp-jscore.c +++ /dev/null @@ -1,518 +0,0 @@ -/* This file contains wrapper functions for pdf_jsimp functions implemented - * in Javascriptcore */ - -#include -#include "mupdf/pdf.h" - -#define STRING_BUF_SIZE (256) -#define FUNCTION_PREAMBLE_LEN (9) - -/* - We need only a single JSClassRef because we store property and method information - in the private data of each object. The JSClassRef is set up to know how to access - that data. -*/ -struct pdf_jsimp_s -{ - fz_context *ctx; - void *nat_ctx; - JSGlobalContextRef jscore_ctx; - JSClassRef class_ref; -}; - -enum -{ - PROP_FN, - PROP_VAL -}; - -typedef struct prop_fn_s -{ - pdf_jsimp_method *meth; -} prop_fn; - -typedef struct prop_val_s -{ - pdf_jsimp_getter *get; - pdf_jsimp_setter *set; -} prop_val; - -typedef struct prop_s -{ - char *name; - int type; - union - { - prop_fn fn; - prop_val val; - } u; -} prop; - -typedef struct prop_list_s prop_list; - -struct prop_list_s -{ - prop prop; - prop_list *next; -}; - -struct pdf_jsimp_type_s -{ - pdf_jsimp *imp; - pdf_jsimp_dtr *dtr; - prop_list *props; -}; - -/* - When we create a JavaScriptCore object, we store in its private data the MuPDF - native object pointer and a pointer to the type. The type has a list of the - properties and methods -*/ -typedef struct priv_data_s -{ - pdf_jsimp_type *type; - void *natobj; -} priv_data; - -struct pdf_jsimp_obj_s -{ - JSValueRef ref; - char *str; -}; - -static prop *find_prop(prop_list *list, char *name) -{ - while (list) - { - if (strcmp(name, list->prop.name) == 0) - return &list->prop; - - list = list->next; - } - - return NULL; -} - -static pdf_jsimp_obj *wrap_val(pdf_jsimp *imp, JSValueRef ref) -{ - pdf_jsimp_obj *obj = fz_malloc_struct(imp->ctx, pdf_jsimp_obj); - obj->ref = ref; - JSValueProtect(imp->jscore_ctx, ref); - - return obj; -} - -static JSValueRef callMethod(JSContextRef jscore_ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) -{ - pdf_jsimp *imp; - fz_context *ctx; - pdf_jsimp_obj *res = NULL; - JSValueRef resref = NULL; - int i; - pdf_jsimp_obj **args = NULL; - pdf_jsimp_method *meth = JSObjectGetPrivate(function); - priv_data *pdata = JSObjectGetPrivate(thisObject); - if (meth == NULL) - { - /* - The attempt to store the method pointer as private data failed, so we - turn the function into a string, which will have the form "function name() xxx", - and then lookup the name. - */ - char name[STRING_BUF_SIZE]; - char *np; - char *bp; - JSStringRef jname = JSValueToStringCopy(jscore_ctx, function, NULL); - prop *p; - JSStringGetUTF8CString(jname, name, STRING_BUF_SIZE); - if (strlen(name) >= FUNCTION_PREAMBLE_LEN) - { - np = name + FUNCTION_PREAMBLE_LEN; /* strlen("function "); */ - bp = strchr(np, '('); - if (bp) - *bp = 0; - p = find_prop(pdata->type->props, np); - if (p && p->type == PROP_FN) - { - meth = p->u.fn.meth; - } - } - JSStringRelease(jname); - } - if (meth == NULL || pdata == NULL) - return JSValueMakeUndefined(jscore_ctx); - - imp = pdata->type->imp; - ctx = imp->ctx; - - fz_var(args); - fz_var(res); - fz_try(ctx) - { - args = fz_malloc_array(ctx, argumentCount, sizeof(pdf_jsimp_obj)); - for (i = 0; i < argumentCount; i++) - args[i] = wrap_val(imp, arguments[i]); - - res = meth(imp->nat_ctx, pdata->natobj, argumentCount, args); - if (res) - resref = res->ref; - } - fz_always(ctx) - { - if (args) - { - for (i = 0; i < argumentCount; i++) - pdf_jsimp_drop_obj(imp, args[i]); - fz_free(ctx, args); - } - pdf_jsimp_drop_obj(imp, res); - } - fz_catch(ctx) - { - return JSValueMakeUndefined(jscore_ctx); - } - - return resref; -} - -static JSValueRef getProperty(JSContextRef jscore_ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef *exception) -{ - pdf_jsimp *imp; - char buf[STRING_BUF_SIZE]; - prop *p; - JSValueRef res = NULL; - - priv_data *pdata = JSObjectGetPrivate(object); - if (pdata == NULL) - return NULL; - - JSStringGetUTF8CString(propertyName, buf, STRING_BUF_SIZE); - p = find_prop(pdata->type->props, buf); - if (p == NULL) - return NULL; - - imp = pdata->type->imp; - - switch(p->type) - { - case PROP_FN: - { - /* - For some reason passing the method pointer as private data doesn't work: the data comes back - NULL when interrogated in callMethod above. So we also specify the method name when - creating the function so that we can look it up again in callMethod. Not ideal, but - will do until we can find a better solution. - */ - JSObjectRef ores = JSObjectMakeFunctionWithCallback(jscore_ctx, propertyName, callMethod); - JSObjectSetPrivate(ores, p->u.fn.meth); - res = ores; - } - break; - - case PROP_VAL: - { - pdf_jsimp_obj *pres = p->u.val.get(imp->nat_ctx, pdata->natobj); - res = pres->ref; - pdf_jsimp_drop_obj(imp, pres); - } - break; - } - - return res; -} - -static bool setProperty(JSContextRef jscore_ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef *exception) -{ - pdf_jsimp *imp; - char buf[STRING_BUF_SIZE]; - prop *p; - - priv_data *pdata = JSObjectGetPrivate(object); - if (pdata == NULL) - return false; - - JSStringGetUTF8CString(propertyName, buf, STRING_BUF_SIZE); - p = find_prop(pdata->type->props, buf); - if (p == NULL) - return false; - - imp = pdata->type->imp; - - switch(p->type) - { - case PROP_FN: - break; - - case PROP_VAL: - { - pdf_jsimp_obj *pval = wrap_val(imp, value); - p->u.val.set(imp->nat_ctx, pdata->natobj, pval); - pdf_jsimp_drop_obj(imp, pval); - } - break; - } - - return true; -} - -pdf_jsimp *pdf_new_jsimp(fz_context *ctx, void *jsctx) -{ - pdf_jsimp *imp = fz_malloc_struct(ctx, pdf_jsimp); - - fz_try(ctx) - { - JSClassDefinition classDef = kJSClassDefinitionEmpty; - - classDef.getProperty = getProperty; - classDef.setProperty = setProperty; - - imp->nat_ctx = jsctx; - imp->class_ref = JSClassCreate(&classDef); - imp->jscore_ctx = JSGlobalContextCreate(imp->class_ref); - if (imp->jscore_ctx == NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "JSGlobalContextCreate failed"); - } - fz_catch(ctx) - { - pdf_drop_jsimp(imp); - fz_rethrow(ctx); - } - - imp->ctx = ctx; - - return imp; -} - -void pdf_drop_jsimp(pdf_jsimp *imp) -{ - if (imp) - { - JSGlobalContextRelease(imp->jscore_ctx); - JSClassRelease(imp->class_ref); - fz_free(imp->ctx, imp); - } -} - -pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr, char *name) -{ - pdf_jsimp_type *type = fz_malloc_struct(imp->ctx, pdf_jsimp_type); - type->imp = imp; - type->dtr = dtr; - return type; -} - -void pdf_jsimp_drop_type(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - if (imp && type) - { - fz_context *ctx = imp->ctx; - prop_list *node; - - while (type->props) - { - node = type->props; - type->props = node->next; - fz_free(ctx, node->prop.name); - fz_free(ctx, node); - } - - fz_free(ctx, type); - } -} - -void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) -{ - fz_context *ctx = imp->ctx; - prop_list *node = fz_malloc_struct(ctx, prop_list); - - fz_try(ctx) - { - node->prop.name = fz_strdup(imp->ctx, name); - node->prop.type = PROP_FN; - node->prop.u.fn.meth = meth; - - node->next = type->props; - type->props = node; - } - fz_catch(ctx) - { - fz_free(ctx, node); - fz_rethrow(ctx); - } -} - -void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) -{ - fz_context *ctx = imp->ctx; - prop_list *node = fz_malloc_struct(ctx, prop_list); - - fz_try(ctx) - { - node->prop.name = fz_strdup(imp->ctx, name); - node->prop.type = PROP_VAL; - node->prop.u.val.get = get; - node->prop.u.val.set = set; - - node->next = type->props; - type->props = node; - } - fz_catch(ctx) - { - fz_free(ctx, node); - fz_rethrow(ctx); - } -} - -void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - fz_context *ctx = imp->ctx; - priv_data *pdata; - JSObjectRef gobj = JSContextGetGlobalObject(imp->jscore_ctx); - if (gobj == NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "JSContextGetGlobalObject failed"); - - pdata = fz_malloc_struct(ctx, priv_data); - pdata->type = type; - pdata->natobj = NULL; - JSObjectSetPrivate(gobj, pdata); -} - -pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj) -{ - fz_context *ctx = imp->ctx; - pdf_jsimp_obj *obj = fz_malloc_struct(ctx, pdf_jsimp_obj); - priv_data *pdata = NULL; - - fz_var(pdata); - fz_try(ctx) - { - pdata = fz_malloc_struct(ctx, priv_data); - pdata->type = type; - pdata->natobj = natobj; - obj->ref = JSObjectMake(imp->jscore_ctx, imp->class_ref, pdata); - if (obj->ref == NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "JSObjectMake failed"); - - JSValueProtect(imp->jscore_ctx, obj->ref); - } - fz_catch(ctx) - { - fz_free(ctx, pdata); - fz_free(ctx, obj); - fz_rethrow(ctx); - } - - return obj; -} - -void pdf_jsimp_drop_obj(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - if (imp && obj) - { - JSValueUnprotect(imp->jscore_ctx, obj->ref); - fz_free(imp->ctx, obj->str); - fz_free(imp->ctx, obj); - } -} - -int pdf_jsimp_to_type(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - switch (JSValueGetType(imp->jscore_ctx, obj->ref)) - { - case kJSTypeNull: return JS_TYPE_NULL; - case kJSTypeBoolean: return JS_TYPE_BOOLEAN; - case kJSTypeNumber: return JS_TYPE_NUMBER; - case kJSTypeString: return JS_TYPE_STRING; - case kJSTypeObject: return JS_TYPE_ARRAY; - default: return JS_TYPE_UNKNOWN; - } -} - -pdf_jsimp_obj *pdf_jsimp_from_string(pdf_jsimp *imp, char *str) -{ - JSStringRef sref = JSStringCreateWithUTF8CString(str); - JSValueRef vref = JSValueMakeString(imp->jscore_ctx, sref); - JSStringRelease(sref); - - return wrap_val(imp, vref); -} - -char *pdf_jsimp_to_string(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - fz_context *ctx = imp->ctx; - JSStringRef jstr = JSValueToStringCopy(imp->jscore_ctx, obj->ref, NULL); - int len; - - if (jstr == NULL) - return ""; - - fz_try(ctx) - { - len = JSStringGetMaximumUTF8CStringSize(jstr); - fz_free(ctx, obj->str); - obj->str = NULL; - obj->str = fz_malloc(ctx, len+1); - JSStringGetUTF8CString(jstr, obj->str, len+1); - } - fz_always(ctx) - { - JSStringRelease(jstr); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } - - return obj->str; -} - -pdf_jsimp_obj *pdf_jsimp_from_number(pdf_jsimp *imp, double num) -{ - return wrap_val(imp, JSValueMakeNumber(imp->jscore_ctx, num)); -} - -double pdf_jsimp_to_number(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - return JSValueToNumber(imp->jscore_ctx, obj->ref, NULL); -} - -int pdf_jsimp_array_len(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - pdf_jsimp_obj *lobj = pdf_jsimp_property(imp, obj, "length"); - int num = (int)pdf_jsimp_to_number(imp, lobj); - - pdf_jsimp_drop_obj(imp, lobj); - - return num; -} - -pdf_jsimp_obj *pdf_jsimp_array_item(pdf_jsimp *imp, pdf_jsimp_obj *obj, int i) -{ - return wrap_val(imp, JSObjectGetPropertyAtIndex(imp->jscore_ctx, JSValueToObject(imp->jscore_ctx, obj->ref, NULL), i, NULL)); -} - -pdf_jsimp_obj *pdf_jsimp_property(pdf_jsimp *imp, pdf_jsimp_obj *obj, char *prop) -{ - JSStringRef jprop = JSStringCreateWithUTF8CString(prop); - JSValueRef jval = JSObjectGetProperty(imp->jscore_ctx, JSValueToObject(imp->jscore_ctx, obj->ref, NULL), jprop, NULL); - - JSStringRelease(jprop); - - return wrap_val(imp, jval); -} - -void pdf_jsimp_execute(pdf_jsimp *imp, char *code) -{ - JSStringRef jcode = JSStringCreateWithUTF8CString(code); - JSEvaluateScript(imp->jscore_ctx, jcode, NULL, NULL, 0, NULL); - JSStringRelease(jcode); -} - -void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count) -{ - char *terminated = fz_malloc(imp->ctx, count+1); - memcpy(terminated, code, count); - terminated[count] = 0; - pdf_jsimp_execute(imp, terminated); - fz_free(imp->ctx, terminated); -} diff --git a/source/pdf/js/pdf-jsimp-mu.c b/source/pdf/js/pdf-jsimp-mu.c deleted file mode 100644 index 2fd918cf..00000000 --- a/source/pdf/js/pdf-jsimp-mu.c +++ /dev/null @@ -1,318 +0,0 @@ -#include "mupdf/pdf.h" - -#include - -#define MAXARGS 16 - -#define OBJ(i) ((pdf_jsimp_obj*)((intptr_t)(i))) -#define IDX(p) ((intptr_t)(p)) -#define NEWOBJ(J,x) OBJ(js_gettop(J) + (x)) - -struct pdf_jsimp_s -{ - fz_context *ctx; - void *jsctx; - js_State *J; -}; - -static void *alloc(void *ud, void *ptr, unsigned int n) -{ - fz_context *ctx = ud; - if (n == 0) { - fz_free(ctx, ptr); - return NULL; - } - if (ptr) - return fz_resize_array(ctx, ptr, n, 1); - return fz_malloc_array(ctx, n, 1); -} - -pdf_jsimp *pdf_new_jsimp(fz_context *ctx, void *jsctx) -{ - js_State *J; - pdf_jsimp *imp; - - J = js_newstate(alloc, ctx, 0); - js_setcontext(J, jsctx); - - imp = fz_malloc_struct(ctx, pdf_jsimp); - imp->ctx = ctx; - imp->jsctx = jsctx; - imp->J = J; - return imp; -} - -void pdf_drop_jsimp(pdf_jsimp *imp) -{ - if (imp) - { - js_freestate(imp->J); - fz_free(imp->ctx, imp); - } -} - -pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr, char *name) -{ - js_State *J = imp->J; - js_newobject(J); - js_setregistry(J, name); - return (pdf_jsimp_type*)name; -} - -void pdf_jsimp_drop_type(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - if (imp && type) - { - js_State *J = imp->J; - js_delregistry(J, (const char *)type); - } -} - -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; - - jsctx = js_getcontext(J); - - js_currentfunction(J); - { - js_getproperty(J, -1, "__call"); - meth = js_touserdata(J, -1, "method"); - 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, 0, type)) - obj = js_touserdata(J, 0, type); - 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 wrapgetter(js_State *J) -{ - pdf_jsimp_obj *ret; - pdf_jsimp_getter *get; - const char *type; - void *jsctx; - void *obj; - - jsctx = js_getcontext(J); - - js_currentfunction(J); - { - js_getproperty(J, -1, "__get"); - get = js_touserdata(J, -1, "getter"); - 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, 0, type)) - obj = js_touserdata(J, 0, type); - else - obj = NULL; - - ret = get(jsctx, obj); - if (ret) - js_copy(J, IDX(ret)); - else - js_pushundefined(J); -} - -static void wrapsetter(js_State *J) -{ - pdf_jsimp_setter *set; - const char *type; - void *jsctx; - void *obj; - - jsctx = js_getcontext(J); - - js_currentfunction(J); - { - js_getproperty(J, -1, "__set"); - set = js_touserdata(J, -1, "setter"); - 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, 0, type)) - obj = js_touserdata(J, 0, type); - else - obj = NULL; - - set(jsctx, obj, OBJ(1)); - - js_pushundefined(J); -} - -void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) -{ - js_State *J = imp->J; - js_getregistry(J, (const char *)type); - { - js_newcfunction(J, wrapmethod, name, 0); - { - js_pushnull(J); - js_newuserdata(J, "method", meth, NULL); - js_defproperty(J, -2, "__call", JS_READONLY | JS_DONTENUM | JS_DONTCONF); - js_pushstring(J, (const char *)type); - js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF); - } - js_defproperty(J, -2, name, JS_READONLY | JS_DONTCONF); - } - js_pop(J, 1); -} - -void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) -{ - js_State *J = imp->J; - js_getregistry(J, (const char *)type); - { - js_newcfunction(J, wrapgetter, name, 0); - { - js_pushnull(J); - js_newuserdata(J, "getter", get, NULL); - js_defproperty(J, -2, "__get", JS_READONLY | JS_DONTENUM | JS_DONTCONF); - js_pushstring(J, (const char *)type); - js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF); - } - js_newcfunction(J, wrapsetter, name, 0); - { - js_pushnull(J); - js_newuserdata(J, "setter", set, NULL); - js_defproperty(J, -2, "__set", JS_READONLY | JS_DONTENUM | JS_DONTCONF); - js_pushstring(J, (const char *)type); - js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF); - } - js_defaccessor(J, -3, name, JS_READONLY | JS_DONTCONF); - } - js_pop(J, 1); -} - -void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - js_State *J = imp->J; - const char *name; - - js_getregistry(J, (const char *)type); - js_pushiterator(J, -1, 1); - while ((name = js_nextiterator(J, -1))) - { - js_getproperty(J, -2, name); - js_setglobal(J, name); - } -} - -pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj) -{ - js_State *J = imp->J; - js_getregistry(J, (const char *)type); - js_newuserdata(J, (const char *)type, natobj, NULL); - return NEWOBJ(J, -1); -} - -void pdf_jsimp_drop_obj(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ -} - -int pdf_jsimp_to_type(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - js_State *J = imp->J; - if (js_isnull(J, IDX(obj))) return JS_TYPE_NULL; - if (js_isboolean(J, IDX(obj))) return JS_TYPE_BOOLEAN; - if (js_isnumber(J, IDX(obj))) return JS_TYPE_NUMBER; - if (js_isstring(J, IDX(obj))) return JS_TYPE_STRING; - if (js_isarray(J, IDX(obj))) return JS_TYPE_ARRAY; - return JS_TYPE_UNKNOWN; -} - -pdf_jsimp_obj *pdf_jsimp_from_string(pdf_jsimp *imp, char *str) -{ - js_State *J = imp->J; - js_pushstring(J, str); - return NEWOBJ(J, -1); -} - -char *pdf_jsimp_to_string(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - /* cast away const :( */ - return (char*)js_tostring(imp->J, IDX(obj)); -} - -pdf_jsimp_obj *pdf_jsimp_from_number(pdf_jsimp *imp, double num) -{ - js_State *J = imp->J; - js_pushnumber(J, num); - return NEWOBJ(J, -1); -} - -double pdf_jsimp_to_number(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - return js_tonumber(imp->J, IDX(obj)); -} - -int pdf_jsimp_array_len(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - js_State *J = imp->J; - return js_getlength(J, IDX(obj)); -} - -pdf_jsimp_obj *pdf_jsimp_array_item(pdf_jsimp *imp, pdf_jsimp_obj *obj, int i) -{ - js_State *J = imp->J; - js_getindex(J, IDX(obj), i); - return NEWOBJ(J, -1); -} - -pdf_jsimp_obj *pdf_jsimp_property(pdf_jsimp *imp, pdf_jsimp_obj *obj, char *prop) -{ - js_State *J = imp->J; - js_getproperty(J, IDX(obj), prop); - return NEWOBJ(J, -1); -} - -void pdf_jsimp_execute(pdf_jsimp *imp, char *code) -{ - js_State *J = imp->J; - js_dostring(J, code, 0); -} - -void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count) -{ - char *terminated = fz_malloc(imp->ctx, count+1); - memcpy(terminated, code, count); - terminated[count] = 0; - pdf_jsimp_execute(imp, terminated); - fz_free(imp->ctx, terminated); -} diff --git a/source/pdf/js/pdf-jsimp-v8.cpp b/source/pdf/js/pdf-jsimp-v8.cpp deleted file mode 100644 index 0a6d5928..00000000 --- a/source/pdf/js/pdf-jsimp-v8.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* - This file contains the v8 implementation of the pdf_jsimp API - */ - -extern "C" { -#include "mupdf/fitz.h" -#include "mupdf/pdf.h" -#include "pdf-jsimp-cpp.h" -} - -#include -#include -#include - -using namespace v8; -using namespace std; - -struct PDFJSImp; - -/* Object we pass to FunctionTemplate::New, which v8 passes back to us in - * callMethod, allowing us to call our client's, passed-in method. */ -struct PDFJSImpMethod -{ - PDFJSImp *imp; - pdf_jsimp_method *meth; - - PDFJSImpMethod(PDFJSImp *imp, pdf_jsimp_method *meth) : imp(imp), meth(meth) {} -}; - -/* Object we pass to ObjectTemplate::SetAccessor, which v8 passes back to us in - * setProp and getProp, allowing us to call our client's, passed-in set/get methods. */ -struct PDFJSImpProperty -{ - PDFJSImp *imp; - pdf_jsimp_getter *get; - pdf_jsimp_setter *set; - - PDFJSImpProperty(PDFJSImp *imp, pdf_jsimp_getter *get, pdf_jsimp_setter *set) : imp(imp), get(get), set(set) {} -}; - -/* Internal representation of the pdf_jsimp_type object */ -struct PDFJSImpType -{ - PDFJSImp *imp; - Persistent templ; - pdf_jsimp_dtr *dtr; - vector methods; - vector properties; - - PDFJSImpType(PDFJSImp *imp, pdf_jsimp_dtr *dtr): imp(imp), dtr(dtr) - { - HandleScope scope; - templ = Persistent::New(ObjectTemplate::New()); - templ->SetInternalFieldCount(1); - } - - ~PDFJSImpType() - { - vector::iterator mit; - for (mit = methods.begin(); mit < methods.end(); mit++) - delete *mit; - - vector::iterator pit; - for (pit = properties.begin(); pit < properties.end(); pit++) - delete *pit; - - templ.Dispose(); - } -}; - -/* Info via which we destroy the client side part of objects that - * v8 garbage collects */ -struct PDFJSImpGCObj -{ - Persistent pobj; - PDFJSImpType *type; - - PDFJSImpGCObj(Handle obj, PDFJSImpType *type): type(type) - { - pobj = Persistent::New(obj); - } - - ~PDFJSImpGCObj() - { - pobj.Dispose(); - } -}; - -/* Internal representation of the pdf_jsimp object */ -struct PDFJSImp -{ - fz_context *ctx; - void *jsctx; - Persistent context; - vector types; - set gclist; - - PDFJSImp(fz_context *ctx, void *jsctx) : ctx(ctx), jsctx(jsctx) - { - HandleScope scope; - context = Persistent::New(Context::New()); - } - - ~PDFJSImp() - { - HandleScope scope; - /* Tell v8 our context will not be used again */ - context.Dispose(); - - /* Unlink and destroy all the objects that v8 has yet to gc */ - set::iterator oit; - for (oit = gclist.begin(); oit != gclist.end(); oit++) - { - (*oit)->pobj.ClearWeak(); /* So that gcCallback wont get called */ - PDFJSImpType *vType = (*oit)->type; - Local owrap = Local::Cast((*oit)->pobj->GetInternalField(0)); - vType->dtr(vType->imp->jsctx, owrap->Value()); - delete *oit; - } - - vector::iterator it; - for (it = types.begin(); it < types.end(); it++) - delete *it; - } -}; - -/* Internal representation of the pdf_jsimp_obj object */ -class PDFJSImpObject -{ - Persistent pobj; - String::Utf8Value *utf8; - -public: - PDFJSImpObject(Handle obj): utf8(NULL) - { - pobj = Persistent::New(obj); - } - - PDFJSImpObject(const char *str): utf8(NULL) - { - pobj = Persistent::New(String::New(str)); - } - - PDFJSImpObject(double num): utf8(NULL) - { - pobj = Persistent::New(Number::New(num)); - } - - ~PDFJSImpObject() - { - delete utf8; - pobj.Dispose(); - } - - int type() - { - if (pobj->IsNull()) - return JS_TYPE_NULL; - else if (pobj->IsString() || pobj->IsStringObject()) - return JS_TYPE_STRING; - else if (pobj->IsNumber() || pobj->IsNumberObject()) - return JS_TYPE_NUMBER; - else if (pobj->IsArray()) - return JS_TYPE_ARRAY; - else if (pobj->IsBoolean() || pobj->IsBooleanObject()) - return JS_TYPE_BOOLEAN; - else - return JS_TYPE_UNKNOWN; - } - - char *toString() - { - delete utf8; - utf8 = new String::Utf8Value(pobj); - return **utf8; - } - - double toNumber() - { - return pobj->NumberValue(); - } - - Handle toValue() - { - return pobj; - } -}; - -extern "C" fz_context *pdf_jsimp_ctx_cpp(pdf_jsimp *imp) -{ - return reinterpret_cast(imp)->ctx; -} - -extern "C" const char *pdf_new_jsimp_cpp(fz_context *ctx, void *jsctx, pdf_jsimp **imp) -{ - Locker lock; - *imp = reinterpret_cast(new PDFJSImp(ctx, jsctx)); - - return NULL; -} - -extern "C" const char *pdf_drop_jsimp_cpp(pdf_jsimp *imp) -{ - Locker lock; - delete reinterpret_cast(imp); - return NULL; -} - -extern "C" const char *pdf_jsimp_new_type_cpp(pdf_jsimp *imp, pdf_jsimp_dtr *dtr, pdf_jsimp_type **type) -{ - Locker lock; - PDFJSImp *vImp = reinterpret_cast(imp); - PDFJSImpType *vType = new PDFJSImpType(vImp, dtr); - vImp->types.push_back(vType); - *type = reinterpret_cast(vType); - return NULL; -} - -extern "C" const char *pdf_jsimp_drop_type_cpp(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - /* Types are recorded and destroyed as part of PDFJSImp */ - return NULL; -} - -static Handle callMethod(const Arguments &args) -{ - HandleScope scope; - Local mwrap = Local::Cast(args.Data()); - PDFJSImpMethod *m = (PDFJSImpMethod *)mwrap->Value(); - - Local self = args.Holder(); - Local owrap; - void *nself = NULL; - if (self->InternalFieldCount() > 0) - { - owrap = Local::Cast(self->GetInternalField(0)); - nself = owrap->Value(); - } - - int c = args.Length(); - PDFJSImpObject **native_args = new PDFJSImpObject*[c]; - for (int i = 0; i < c; i++) - native_args[i] = new PDFJSImpObject(args[i]); - - PDFJSImpObject *obj = reinterpret_cast(pdf_jsimp_call_method(reinterpret_cast(m->imp), m->meth, m->imp->jsctx, nself, c, reinterpret_cast(native_args))); - Handle val; - if (obj) - val = obj->toValue(); - delete obj; - - for (int i = 0; i < c; i++) - delete native_args[i]; - - delete native_args; - - return scope.Close(val); -} - -extern "C" const char *pdf_jsimp_addmethod_cpp(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) -{ - Locker lock; - PDFJSImpType *vType = reinterpret_cast(type); - HandleScope scope; - - PDFJSImpMethod *pmeth = new PDFJSImpMethod(vType->imp, meth); - vType->templ->Set(String::New(name), FunctionTemplate::New(callMethod, External::New(pmeth))); - vType->methods.push_back(pmeth); - return NULL; -} - -static Handle getProp(Local property, const AccessorInfo &info) -{ - HandleScope scope; - Local pwrap = Local::Cast(info.Data()); - PDFJSImpProperty *p = reinterpret_cast(pwrap->Value()); - - Local self = info.Holder(); - Local owrap; - void *nself = NULL; - if (self->InternalFieldCount() > 0) - { - Local val = self->GetInternalField(0); - if (val->IsExternal()) - { - owrap = Local::Cast(val); - nself = owrap->Value(); - } - } - - PDFJSImpObject *obj = reinterpret_cast(pdf_jsimp_call_getter(reinterpret_cast(p->imp), p->get, p->imp->jsctx, nself)); - Handle val; - if (obj) - val = obj->toValue(); - delete obj; - return scope.Close(val); -} - -static void setProp(Local property, Local value, const AccessorInfo &info) -{ - HandleScope scope; - Local wrap = Local::Cast(info.Data()); - PDFJSImpProperty *p = reinterpret_cast(wrap->Value()); - - Local self = info.Holder(); - Local owrap; - void *nself = NULL; - if (self->InternalFieldCount() > 0) - { - owrap = Local::Cast(self->GetInternalField(0)); - nself = owrap->Value(); - } - - PDFJSImpObject *obj = new PDFJSImpObject(value); - - pdf_jsimp_call_setter(reinterpret_cast(p->imp), p->set, p->imp->jsctx, nself, reinterpret_cast(obj)); - delete obj; -} - -extern "C" const char *pdf_jsimp_addproperty_cpp(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) -{ - Locker lock; - PDFJSImpType *vType = reinterpret_cast(type); - HandleScope scope; - - PDFJSImpProperty *prop = new PDFJSImpProperty(vType->imp, get, set); - vType->templ->SetAccessor(String::New(name), getProp, setProp, External::New(prop)); - vType->properties.push_back(prop); - return NULL; -} - -extern "C" const char *pdf_jsimp_set_global_type_cpp(pdf_jsimp *imp, pdf_jsimp_type *type) -{ - Locker lock; - PDFJSImp *vImp = reinterpret_cast(imp); - PDFJSImpType *vType = reinterpret_cast(type); - HandleScope scope; - - vImp->context = Persistent::New(Context::New(NULL, vType->templ)); - return NULL; -} - -static void gcCallback(Persistent val, void *parm) -{ - PDFJSImpGCObj *gco = reinterpret_cast(parm); - PDFJSImpType *vType = gco->type; - HandleScope scope; - Persistent obj = Persistent::Cast(val); - - Local owrap = Local::Cast(obj->GetInternalField(0)); - vType->dtr(vType->imp->jsctx, owrap->Value()); - vType->imp->gclist.erase(gco); - delete gco; /* Disposes of the persistent handle */ -} - -extern "C" const char *pdf_jsimp_new_obj_cpp(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj, pdf_jsimp_obj **robj) -{ - Locker lock; - PDFJSImpType *vType = reinterpret_cast(type); - HandleScope scope; - Local obj = vType->templ->NewInstance(); - obj->SetInternalField(0, External::New(natobj)); - - /* Arrange for destructor to be called on the client-side object - * when the v8 object is garbage collected */ - if (vType->dtr) - { - /* Wrap obj in a PDFJSImpGCObj, which takes a persistent handle to - * obj, and stores its type with it. The persistent handle tells v8 - * it cannot just destroy obj leaving the client-side object hanging */ - PDFJSImpGCObj *gco = new PDFJSImpGCObj(obj, vType); - /* Keep the wrapped object in a list, so that we can take back control - * of destroying client-side objects when shutting down this context */ - vType->imp->gclist.insert(gco); - /* Tell v8 that it can destroy the persistent handle to obj when it has - * no further need for it, but it must inform us via gcCallback */ - gco->pobj.MakeWeak(gco, gcCallback); - } - - *robj = reinterpret_cast(new PDFJSImpObject(obj)); - return NULL; -} - -extern "C" const char *pdf_jsimp_drop_obj_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj) -{ - Locker lock; - delete reinterpret_cast(obj); - return NULL; -} - -extern "C" const char *pdf_jsimp_to_type_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, int *type) -{ - Locker lock; - *type = reinterpret_cast(obj)->type(); - return NULL; -} - -extern "C" const char *pdf_jsimp_from_string_cpp(pdf_jsimp *imp, char *str, pdf_jsimp_obj **obj) -{ - Locker lock; - *obj = reinterpret_cast(new PDFJSImpObject(str)); - return NULL; -} - -extern "C" const char *pdf_jsimp_to_string_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, char **str) -{ - Locker lock; - *str = reinterpret_cast(obj)->toString(); - return NULL; -} - -extern "C" const char *pdf_jsimp_from_number_cpp(pdf_jsimp *imp, double num, pdf_jsimp_obj **obj) -{ - Locker lock; - *obj = reinterpret_cast(new PDFJSImpObject(num)); - return NULL; -} - -extern "C" const char *pdf_jsimp_to_number_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, double *num) -{ - Locker lock; - *num = reinterpret_cast(obj)->toNumber(); - return NULL; -} - -extern "C" const char *pdf_jsimp_array_len_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, int *len) -{ - Locker lock; - Local jsobj = reinterpret_cast(obj)->toValue()->ToObject(); - Local arr = Local::Cast(jsobj); - *len = arr->Length(); - return NULL; -} - -extern "C" const char *pdf_jsimp_array_item_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, int i, pdf_jsimp_obj **item) -{ - Locker lock; - Local jsobj = reinterpret_cast(obj)->toValue()->ToObject(); - *item = reinterpret_cast(new PDFJSImpObject(jsobj->Get(Number::New(i)))); - return NULL; -} - -extern "C" const char *pdf_jsimp_property_cpp(pdf_jsimp *imp, pdf_jsimp_obj *obj, char *prop, pdf_jsimp_obj **pobj) -{ - Locker lock; - Local jsobj = reinterpret_cast(obj)->toValue()->ToObject(); - *pobj = reinterpret_cast(new PDFJSImpObject(jsobj->Get(String::New(prop)))); - return NULL; -} - -extern "C" const char *pdf_jsimp_execute_cpp(pdf_jsimp *imp, char *code) -{ - Locker lock; - PDFJSImp *vImp = reinterpret_cast(imp); - HandleScope scope; - Context::Scope context_scope(vImp->context); - Handle