diff --git a/src/ecmascript/spidermonkey-shared.c b/src/ecmascript/spidermonkey-shared.c index bb7f3cae..ab1d5829 100644 --- a/src/ecmascript/spidermonkey-shared.c +++ b/src/ecmascript/spidermonkey-shared.c @@ -8,6 +8,8 @@ #include "elinks.h" #include "ecmascript/spidermonkey-shared.h" +#include "ecmascript/spidermonkey.h" +#include "scripting/smjs/core.h" /** A shared runtime used for both user scripts (scripting/smjs/) and * scripts on web pages (ecmascript/spidermonkey/). @@ -31,6 +33,38 @@ JSContext *spidermonkey_empty_context; * it can be initialized and shut down in arbitrary order. */ static int spidermonkey_runtime_refcount; +static void +error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) +{ + /* We have three types of JSContexts. + * - spidermonkey_empty_context never has anything defined or + * evaluated in it, so this error_reporter() should not be + * called for it. + * - smjs_ctx for user scripts. + * - many JSContexts for web scripts. + * Check which one ctx is and call the appropriate function. + * + * Instead of the scheme used here, we could: + * (a) make the private pointer of every context point to a + * structure of known type and put a function pointer or + * enum in that structure, or + * (b) assume that JS_GetContextPrivate(smjs_ctx) == NULL. */ + + assert(ctx != spidermonkey_empty_context); + if_assert_failed return; + +#ifdef CONFIG_SCRIPTING_SPIDERMONKEY + if (ctx == smjs_ctx) { + smjs_error_reporter(ctx, message, report); + return; + } +#endif + +#ifdef CONFIG_ECMASCRIPT_SMJS + spidermonkey_error_reporter(ctx, message, report); +#endif +} + /** Initialize ::spidermonkey_runtime and ::spidermonkey_empty_context. * If already initialized, just increment the reference count. * @@ -58,6 +92,11 @@ spidermonkey_runtime_addref(void) JS_ShutDown(); return 0; } + + /* Although JS_SetErrorReporter gets the JSContext as + * a parameter, it affects the whole JSRuntime. */ + JS_SetErrorReporter(spidermonkey_empty_context, + error_reporter); } assert(spidermonkey_runtime); diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c index 267f81c5..d5d10304 100644 --- a/src/ecmascript/spidermonkey.c +++ b/src/ecmascript/spidermonkey.c @@ -57,8 +57,8 @@ static int js_module_init_ok; -static void -error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) +void +spidermonkey_error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) { struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct terminal *term; @@ -171,7 +171,6 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter) /* XXX: JSOPTION_COMPILE_N_GO will go (will it?) when we implement * some kind of bytecode cache. (If we will ever do that.) */ JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_COMPILE_N_GO); - JS_SetErrorReporter(ctx, error_reporter); window_obj = JS_NewObject(ctx, (JSClass *) &window_class, NULL, NULL); if (!window_obj) { diff --git a/src/ecmascript/spidermonkey.h b/src/ecmascript/spidermonkey.h index 119ff802..13d086a1 100644 --- a/src/ecmascript/spidermonkey.h +++ b/src/ecmascript/spidermonkey.h @@ -2,6 +2,10 @@ #define EL__ECMASCRIPT_SPIDERMONKEY_H struct ecmascript_interpreter; +struct form_state; +struct form_view; +struct JSContext; +struct JSErrorReport; struct string; void *spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter); @@ -15,5 +19,7 @@ void spidermonkey_eval(struct ecmascript_interpreter *interpreter, struct string unsigned char *spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter, struct string *code); int spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter, struct string *code); +void spidermonkey_error_reporter(struct JSContext *ctx, const char *message, struct JSErrorReport *report); + extern struct module spidermonkey_module; #endif diff --git a/src/scripting/smjs/core.c b/src/scripting/smjs/core.c index a5235c1b..7fa296a8 100644 --- a/src/scripting/smjs/core.c +++ b/src/scripting/smjs/core.c @@ -33,8 +33,8 @@ alert_smjs_error(unsigned char *msg) smjs_ses, msg); } -static void -error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) +void +smjs_error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) { unsigned char *strict, *exception, *warning, *error; struct string msg; @@ -127,14 +127,15 @@ init_smjs(struct module *module) { if (!spidermonkey_runtime_addref()) return; + /* Set smjs_ctx immediately after creating the JSContext, so + * that any error reports from SpiderMonkey are forwarded to + * smjs_error_reporter(). */ smjs_ctx = JS_NewContext(spidermonkey_runtime, 8192); if (!smjs_ctx) { spidermonkey_runtime_release(); return; } - JS_SetErrorReporter(smjs_ctx, error_reporter); - smjs_init_global_object(); smjs_init_elinks_object(); diff --git a/src/scripting/smjs/core.h b/src/scripting/smjs/core.h index 0542f5cb..ffbc82c1 100644 --- a/src/scripting/smjs/core.h +++ b/src/scripting/smjs/core.h @@ -10,6 +10,7 @@ struct string; extern JSContext *smjs_ctx; extern struct session *smjs_ses; +void smjs_error_reporter(JSContext *ctx, const char *message, JSErrorReport *report); void alert_smjs_error(unsigned char *msg); void init_smjs(struct module *module);