From b94657869bc90b5c42693c28c472f041a80fced1 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 7 Sep 2008 19:39:26 +0300 Subject: [PATCH] 1031: JS_SetErrorReporter only once per JSRuntime. Previously, spidermonkey_get_interpreter() and init_smjs() each called JS_SetErrorReporter on the JSContexts they created. However, JS_SetErrorReporter actually sets the error reporter of the JSRuntime associated with the JSContext, and all of our JSContexts use the same JSRuntime nowadays, so only the error_reporter() of src/ecmascript/spidermonkey.c was left installed. Because this error_reporter() asserts that JS_GetContextPrivate(ctx) returns a non-NULL pointer, and init_smjs() does not set a private pointer for smjs_ctx, any error in smjs_ctx could cause an assertion failure, at least in principle. Fix this by making spidermonkey_runtime_addref() install a shared error_reporter() when it creates the JSRuntime and the first JSContext. The shared error_reporter() then checks the JSContext and calls the appropriate function. The two error reporters are quite similar with each other. In the future, we could move the common code into shared functions. I'm not doing that yet though, because fixing the bug doesn't require it. --- src/ecmascript/spidermonkey-shared.c | 39 ++++++++++++++++++++++++++++ src/ecmascript/spidermonkey.c | 5 ++-- src/ecmascript/spidermonkey.h | 6 +++++ src/scripting/smjs/core.c | 9 ++++--- src/scripting/smjs/core.h | 1 + 5 files changed, 53 insertions(+), 7 deletions(-) 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);