Bug 342737: New API to register JS_NewContext/JS_DestroyContext* callback. In this way an embedding can do a common customization of JSContext instances in a single place. r=brendan

This commit is contained in:
igor.bukanov%gmail.com 2006-06-27 12:09:09 +00:00
Родитель 0160424edb
Коммит d115537fbf
5 изменённых файлов: 74 добавлений и 10 удалений

Просмотреть файл

@ -930,6 +930,16 @@ JS_Unlock(JSRuntime *rt)
JS_UNLOCK_RUNTIME(rt); JS_UNLOCK_RUNTIME(rt);
} }
JS_PUBLIC_API(JSContextCallback)
JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
{
JSContextCallback old;
old = rt->cxCallback;
rt->cxCallback = cxCallback;
return old;
}
JS_PUBLIC_API(JSContext *) JS_PUBLIC_API(JSContext *)
JS_NewContext(JSRuntime *rt, size_t stackChunkSize) JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
{ {
@ -939,19 +949,19 @@ JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_DestroyContext(JSContext *cx) JS_DestroyContext(JSContext *cx)
{ {
js_DestroyContext(cx, JS_FORCE_GC); js_DestroyContext(cx, JSDCM_FORCE_GC);
} }
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_DestroyContextNoGC(JSContext *cx) JS_DestroyContextNoGC(JSContext *cx)
{ {
js_DestroyContext(cx, JS_NO_GC); js_DestroyContext(cx, JSDCM_NO_GC);
} }
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_DestroyContextMaybeGC(JSContext *cx) JS_DestroyContextMaybeGC(JSContext *cx)
{ {
js_DestroyContext(cx, JS_MAYBE_GC); js_DestroyContext(cx, JSDCM_MAYBE_GC);
} }
JS_PUBLIC_API(void *) JS_PUBLIC_API(void *)

Просмотреть файл

@ -437,6 +437,9 @@ JS_Lock(JSRuntime *rt);
extern JS_PUBLIC_API(void) extern JS_PUBLIC_API(void)
JS_Unlock(JSRuntime *rt); JS_Unlock(JSRuntime *rt);
extern JS_PUBLIC_API(JSContextCallback)
JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback);
extern JS_PUBLIC_API(JSContext *) extern JS_PUBLIC_API(JSContext *)
JS_NewContext(JSRuntime *rt, size_t stackChunkSize); JS_NewContext(JSRuntime *rt, size_t stackChunkSize);

Просмотреть файл

@ -168,6 +168,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
{ {
JSContext *cx; JSContext *cx;
JSBool ok, first; JSBool ok, first;
JSContextCallback cxCallback;
cx = (JSContext *) malloc(sizeof *cx); cx = (JSContext *) malloc(sizeof *cx);
if (!cx) if (!cx)
@ -214,7 +215,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
JS_InitArenaPool(&cx->tempPool, "temp", 1024, sizeof(jsdouble)); JS_InitArenaPool(&cx->tempPool, "temp", 1024, sizeof(jsdouble));
if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) { if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
js_DestroyContext(cx, JS_NO_GC); js_DestroyContext(cx, JSDCM_NEW_FAILED);
return NULL; return NULL;
} }
@ -250,7 +251,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
JS_EndRequest(cx); JS_EndRequest(cx);
#endif #endif
if (!ok) { if (!ok) {
js_DestroyContext(cx, JS_NO_GC); js_DestroyContext(cx, JSDCM_NEW_FAILED);
return NULL; return NULL;
} }
@ -260,13 +261,19 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
JS_UNLOCK_GC(rt); JS_UNLOCK_GC(rt);
} }
cxCallback = rt->cxCallback;
if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
js_DestroyContext(cx, JSDCM_NEW_FAILED);
return NULL;
}
return cx; return cx;
} }
void void
js_DestroyContext(JSContext *cx, JSGCMode gcmode) js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
{ {
JSRuntime *rt; JSRuntime *rt;
JSContextCallback cxCallback;
JSBool last; JSBool last;
JSArgumentFormatMap *map; JSArgumentFormatMap *map;
JSLocalRootStack *lrs; JSLocalRootStack *lrs;
@ -274,6 +281,21 @@ js_DestroyContext(JSContext *cx, JSGCMode gcmode)
rt = cx->runtime; rt = cx->runtime;
if (mode != JSDCM_NEW_FAILED) {
cxCallback = rt->cxCallback;
if (cxCallback) {
/*
* JSCONTEXT_DESTROY callback is not allowed to fail and must
* return true.
*/
#ifdef DEBUG
JSBool callbackStatus =
#endif
cxCallback(cx, JSCONTEXT_DESTROY);
JS_ASSERT(callbackStatus);
}
}
/* Remove cx from context list first. */ /* Remove cx from context list first. */
JS_LOCK_GC(rt); JS_LOCK_GC(rt);
JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING); JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
@ -357,9 +379,9 @@ js_DestroyContext(JSContext *cx, JSGCMode gcmode)
JS_NOTIFY_ALL_CONDVAR(rt->stateChange); JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
JS_UNLOCK_GC(rt); JS_UNLOCK_GC(rt);
} else { } else {
if (gcmode == JS_FORCE_GC) if (mode == JSDCM_FORCE_GC)
js_ForceGC(cx, 0); js_ForceGC(cx, 0);
else if (gcmode == JS_MAYBE_GC) else if (mode == JSDCM_MAYBE_GC)
JS_MaybeGC(cx); JS_MaybeGC(cx);
} }

Просмотреть файл

@ -94,7 +94,12 @@ js_GetCurrentThread(JSRuntime *rt);
#endif /* JS_THREADSAFE */ #endif /* JS_THREADSAFE */
typedef enum JSGCMode { JS_NO_GC, JS_MAYBE_GC, JS_FORCE_GC } JSGCMode; typedef enum JSDestroyContextMode {
JSDCM_NO_GC,
JSDCM_MAYBE_GC,
JSDCM_FORCE_GC,
JSDCM_NEW_FAILED
} JSDestroyContextMode;
typedef enum JSRuntimeState { typedef enum JSRuntimeState {
JSRTS_DOWN, JSRTS_DOWN,
@ -117,6 +122,9 @@ struct JSRuntime {
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */ /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
JSRuntimeState state; JSRuntimeState state;
/* Context create/destroy callback. */
JSContextCallback cxCallback;
/* Garbage collector state, used by jsgc.c. */ /* Garbage collector state, used by jsgc.c. */
JSGCArenaList gcArenaList[GC_NUM_FREELISTS]; JSGCArenaList gcArenaList[GC_NUM_FREELISTS];
JSDHashTable gcRootsHash; JSDHashTable gcRootsHash;
@ -735,7 +743,7 @@ extern JSContext *
js_NewContext(JSRuntime *rt, size_t stackChunkSize); js_NewContext(JSRuntime *rt, size_t stackChunkSize);
extern void extern void
js_DestroyContext(JSContext *cx, JSGCMode gcmode); js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
/* /*
* Return true if cx points to a context in rt->contextList, else return false. * Return true if cx points to a context in rt->contextList, else return false.

Просмотреть файл

@ -541,6 +541,27 @@ typedef JSBool
/* Callbacks and their arguments. */ /* Callbacks and their arguments. */
typedef enum JSContextOp {
JSCONTEXT_NEW,
JSCONTEXT_DESTROY
} JSContextOp;
/*
* The possible values for contextOp when the runtime calls the callback are:
* JSCONTEXT_NEW JS_NewContext succesfully created a new JSContext
* instance. The callback can initialize the instance as
* required. If the callback returns false, the instance
* will be destroyed and JS_NewContext returns null. In
* this case the callback is not called again.
* JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
* callback may perform its own cleanup and must always
* return true.
* Any other value For future compatibility the callback must do nothing
* and return true in this case.
*/
typedef JSBool
(* JS_DLL_CALLBACK JSContextCallback)(JSContext *cx, uintN contextOp);
typedef enum JSGCStatus { typedef enum JSGCStatus {
JSGC_BEGIN, JSGC_BEGIN,
JSGC_END, JSGC_END,