From 96a54896ee453a453b25a9c9e5c6ba8d0caba7cc Mon Sep 17 00:00:00 2001
From: Tor Andersson <tor.andersson@artifex.com>
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 -----------------
 6 files changed, 409 insertions(+), 2212 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/js')

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 <JavaScriptCore/JavaScriptCore.h>
-#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 <mujs.h>
-
-#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 <vector>
-#include <set>
-#include <v8.h>
-
-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<ObjectTemplate> templ;
-	pdf_jsimp_dtr             *dtr;
-	vector<PDFJSImpMethod *> methods;
-	vector<PDFJSImpProperty *> properties;
-
-	PDFJSImpType(PDFJSImp *imp, pdf_jsimp_dtr *dtr): imp(imp), dtr(dtr)
-	{
-		HandleScope scope;
-		templ = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
-		templ->SetInternalFieldCount(1);
-	}
-
-	~PDFJSImpType()
-	{
-		vector<PDFJSImpMethod *>::iterator mit;
-		for (mit = methods.begin(); mit < methods.end(); mit++)
-			delete *mit;
-
-		vector<PDFJSImpProperty *>::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<Object> pobj;
-	PDFJSImpType *type;
-
-	PDFJSImpGCObj(Handle<Object> obj, PDFJSImpType *type): type(type)
-	{
-		pobj = Persistent<Object>::New(obj);
-	}
-
-	~PDFJSImpGCObj()
-	{
-		pobj.Dispose();
-	}
-};
-
-/* Internal representation of the pdf_jsimp object */
-struct PDFJSImp
-{
-	fz_context			*ctx;
-	void				*jsctx;
-	Persistent<Context>	 context;
-	vector<PDFJSImpType *> types;
-	set<PDFJSImpGCObj *> gclist;
-
-	PDFJSImp(fz_context *ctx, void *jsctx) : ctx(ctx), jsctx(jsctx)
-	{
-		HandleScope scope;
-		context = Persistent<Context>::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<PDFJSImpGCObj *>::iterator oit;
-		for (oit = gclist.begin(); oit != gclist.end(); oit++)
-		{
-			(*oit)->pobj.ClearWeak(); /* So that gcCallback wont get called */
-			PDFJSImpType *vType = (*oit)->type;
-			Local<External> owrap = Local<External>::Cast((*oit)->pobj->GetInternalField(0));
-			vType->dtr(vType->imp->jsctx, owrap->Value());
-			delete *oit;
-		}
-
-		vector<PDFJSImpType *>::iterator it;
-		for (it = types.begin(); it < types.end(); it++)
-			delete *it;
-	}
-};
-
-/* Internal representation of the pdf_jsimp_obj object */
-class PDFJSImpObject
-{
-	Persistent<Value>   pobj;
-	String::Utf8Value  *utf8;
-
-public:
-	PDFJSImpObject(Handle<Value> obj): utf8(NULL)
-	{
-		pobj = Persistent<Value>::New(obj);
-	}
-
-	PDFJSImpObject(const char *str): utf8(NULL)
-	{
-		pobj = Persistent<Value>::New(String::New(str));
-	}
-
-	PDFJSImpObject(double num): utf8(NULL)
-	{
-		pobj = Persistent<Value>::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<Value> toValue()
-	{
-		return pobj;
-	}
-};
-
-extern "C" fz_context *pdf_jsimp_ctx_cpp(pdf_jsimp *imp)
-{
-	return reinterpret_cast<PDFJSImp *>(imp)->ctx;
-}
-
-extern "C" const char *pdf_new_jsimp_cpp(fz_context *ctx, void *jsctx, pdf_jsimp **imp)
-{
-	Locker lock;
-	*imp = reinterpret_cast<pdf_jsimp *>(new PDFJSImp(ctx, jsctx));
-
-	return NULL;
-}
-
-extern "C" const char *pdf_drop_jsimp_cpp(pdf_jsimp *imp)
-{
-	Locker lock;
-	delete reinterpret_cast<PDFJSImp *>(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<PDFJSImp *>(imp);
-	PDFJSImpType *vType = new PDFJSImpType(vImp, dtr);
-	vImp->types.push_back(vType);
-	*type = reinterpret_cast<pdf_jsimp_type *>(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<Value> callMethod(const Arguments &args)
-{
-	HandleScope scope;
-	Local<External> mwrap = Local<External>::Cast(args.Data());
-	PDFJSImpMethod *m = (PDFJSImpMethod *)mwrap->Value();
-
-	Local<Object> self = args.Holder();
-	Local<External> owrap;
-	void *nself = NULL;
-	if (self->InternalFieldCount() > 0)
-	{
-		owrap = Local<External>::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<PDFJSImpObject *>(pdf_jsimp_call_method(reinterpret_cast<pdf_jsimp *>(m->imp), m->meth, m->imp->jsctx, nself, c, reinterpret_cast<pdf_jsimp_obj **>(native_args)));
-	Handle<Value> 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<PDFJSImpType *>(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<Value> getProp(Local<String> property, const AccessorInfo &info)
-{
-	HandleScope scope;
-	Local<External> pwrap = Local<External>::Cast(info.Data());
-	PDFJSImpProperty *p = reinterpret_cast<PDFJSImpProperty *>(pwrap->Value());
-
-	Local<Object> self = info.Holder();
-	Local<External> owrap;
-	void *nself = NULL;
-	if (self->InternalFieldCount() > 0)
-	{
-		Local<Value> val = self->GetInternalField(0);
-		if (val->IsExternal())
-		{
-			owrap = Local<External>::Cast(val);
-			nself = owrap->Value();
-		}
-	}
-
-	PDFJSImpObject *obj = reinterpret_cast<PDFJSImpObject *>(pdf_jsimp_call_getter(reinterpret_cast<pdf_jsimp *>(p->imp), p->get, p->imp->jsctx, nself));
-	Handle<Value> val;
-	if (obj)
-		val = obj->toValue();
-	delete obj;
-	return scope.Close(val);
-}
-
-static void setProp(Local<String> property, Local<Value> value, const AccessorInfo &info)
-{
-	HandleScope scope;
-	Local<External> wrap = Local<External>::Cast(info.Data());
-	PDFJSImpProperty *p = reinterpret_cast<PDFJSImpProperty *>(wrap->Value());
-
-	Local<Object> self = info.Holder();
-	Local<External> owrap;
-	void *nself = NULL;
-	if (self->InternalFieldCount() > 0)
-	{
-		owrap = Local<External>::Cast(self->GetInternalField(0));
-		nself = owrap->Value();
-	}
-
-	PDFJSImpObject *obj = new PDFJSImpObject(value);
-
-	pdf_jsimp_call_setter(reinterpret_cast<pdf_jsimp *>(p->imp), p->set, p->imp->jsctx, nself, reinterpret_cast<pdf_jsimp_obj *>(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<PDFJSImpType *>(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<PDFJSImp *>(imp);
-	PDFJSImpType *vType = reinterpret_cast<PDFJSImpType *>(type);
-	HandleScope scope;
-
-	vImp->context = Persistent<Context>::New(Context::New(NULL, vType->templ));
-	return NULL;
-}
-
-static void gcCallback(Persistent<Value> val, void *parm)
-{
-	PDFJSImpGCObj *gco = reinterpret_cast<PDFJSImpGCObj *>(parm);
-	PDFJSImpType *vType = gco->type;
-	HandleScope scope;
-	Persistent<Object> obj = Persistent<Object>::Cast(val);
-
-	Local<External> owrap = Local<External>::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<PDFJSImpType *>(type);
-	HandleScope scope;
-	Local<Object> 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<pdf_jsimp_obj *>(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<PDFJSImpObject *>(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<PDFJSImpObject *>(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<pdf_jsimp_obj *>(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<PDFJSImpObject *>(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<pdf_jsimp_obj *>(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<PDFJSImpObject *>(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<Object> jsobj = reinterpret_cast<PDFJSImpObject *>(obj)->toValue()->ToObject();
-	Local<Array> arr = Local<Array>::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<Object> jsobj = reinterpret_cast<PDFJSImpObject *>(obj)->toValue()->ToObject();
-	*item = reinterpret_cast<pdf_jsimp_obj *>(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<Object> jsobj = reinterpret_cast<PDFJSImpObject *>(obj)->toValue()->ToObject();
-	*pobj = reinterpret_cast<pdf_jsimp_obj *>(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<PDFJSImp *>(imp);
-	HandleScope scope;
-	Context::Scope context_scope(vImp->context);
-	Handle<Script> script = Script::Compile(String::New(code));
-	if (script.IsEmpty())
-		return "compile failed in pdf_jsimp_execute";
-	script->Run();
-	return NULL;
-}
-
-extern "C" const char *pdf_jsimp_execute_count_cpp(pdf_jsimp *imp, char *code, int count)
-{
-	Locker lock;
-	PDFJSImp *vImp = reinterpret_cast<PDFJSImp *>(imp);
-	HandleScope scope;
-	Context::Scope context_scope(vImp->context);
-	Handle<Script> script = Script::Compile(String::New(code, count));
-	if (script.IsEmpty())
-		return "compile failed in pdf_jsimp_execute_count";
-	script->Run();
-	return NULL;
-}
-- 
cgit v1.2.3