1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-09-12 00:34:47 -04:00

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.
This commit is contained in:
Kalle Olavi Niemitalo 2008-09-07 19:39:26 +03:00 committed by Kalle Olavi Niemitalo
parent 0ee1d05d81
commit b94657869b
5 changed files with 53 additions and 7 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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();

View File

@ -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);