Example #1
0
JSBool
jsd_SetErrorReporter(JSDContext*       jsdc, 
                     JSD_ErrorReporter reporter, 
                     void*             callerdata)
{
    JSD_LOCK();
    jsdc->errorReporter = reporter;
    jsdc->errorReporterData = callerdata;
    JSD_UNLOCK();
    return JS_TRUE;
}
Example #2
0
JSBool
jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
{
    JSD_LOCK();
    if( hook )
        *hook = jsdc->scriptHook;
    if( callerdata )
        *callerdata = jsdc->scriptHookData;
    JSD_UNLOCK();
    return JS_TRUE;
}    
Example #3
0
JSBool
jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable)
{
    JSCompartment* oldCompartment;
    JSBool rv;
    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
    JSD_LOCK();
    rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable);
    JSD_UNLOCK();
    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
    return rv;
}
Example #4
0
JSBool
jsd_ClearAllExecutionHooks(JSDContext* jsdc)
{
    JSDScript* jsdscript;
    JSDScript* iterp = NULL;

    JSD_LOCK();
    while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
        jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
    JSD_UNLOCK();
    return JS_TRUE;
}
Example #5
0
bool
jsd_SetDebuggerHook(JSDContext*           jsdc,
                      JSD_ExecutionHookProc hook,
                      void*                 callerdata)
{
    JSD_LOCK();
    jsdc->debuggerHookData  = callerdata;
    jsdc->debuggerHook      = hook;
    JSD_UNLOCK();

    return true;
}
Example #6
0
JSBool
jsd_SetThrowHook(JSDContext*           jsdc,
                 JSD_ExecutionHookProc hook,
                 void*                 callerdata)
{
    JSD_LOCK();
    jsdc->throwHookData  = callerdata;
    jsdc->throwHook      = hook;
    JSD_UNLOCK();

    return JS_TRUE;
}
Example #7
0
JSBool
jsd_SetFunctionHook(JSDContext*      jsdc,
                    JSD_CallHookProc hook,
                    void*            callerdata)
{
    JSD_LOCK();
    jsdc->functionHookData  = callerdata;
    jsdc->functionHook      = hook;
    JSD_UNLOCK();

    return JS_TRUE;
}
Example #8
0
JSBool
jsd_SetTopLevelHook(JSDContext*      jsdc,
                    JSD_CallHookProc hook,
                    void*            callerdata)
{
    JSD_LOCK();
    jsdc->toplevelHookData  = callerdata;
    jsdc->toplevelHook      = hook;
    JSD_UNLOCK();

    return JS_TRUE;
}
Example #9
0
JSBool
jsd_GetErrorReporter(JSDContext*        jsdc, 
                     JSD_ErrorReporter* reporter, 
                     void**             callerdata)
{
    JSD_LOCK();
    if( reporter )
        *reporter = jsdc->errorReporter;
    if( callerdata )
        *callerdata = jsdc->errorReporterData;
    JSD_UNLOCK();
    return JS_TRUE;
}
Example #10
0
JSBool
jsd_SetInterruptHook(JSDContext*           jsdc,
                     JSD_ExecutionHookProc hook,
                     void*                 callerdata)
{
    JSD_LOCK();
    jsdc->interruptHookData  = callerdata;
    jsdc->interruptHook      = hook;
    JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
    JSD_UNLOCK();

    return JS_TRUE;
}
Example #11
0
JSBool
jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable)
{
    JSCrossCompartmentCall *call;
    JSBool rv;
    call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
    if(!call)
        return JS_FALSE;
    JSD_LOCK();
    rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable);
    JSD_UNLOCK();
    JS_LeaveCrossCompartmentCall(call);
    return rv;
}
Example #12
0
void
jsd_DestroyScriptHookProc( 
                JSFreeOp    *fop,
                JSScript    *script_,
                void*       callerdata )
{
    JSDScript* jsdscript = NULL;
    JSDContext* jsdc = (JSDContext*) callerdata;
    JS::RootedScript script(jsdc->dumbContext, script_);
    JSD_ScriptHookProc      hook;
    void*                   hookData;

    JSD_ASSERT_VALID_CONTEXT(jsdc);

    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
        return;

    JSD_LOCK_SCRIPTS(jsdc);
    jsdscript = jsd_FindJSDScript(jsdc, script);
    JSD_UNLOCK_SCRIPTS(jsdc);

    if( ! jsdscript )
        return;

#ifdef JSD_DUMP
    JSD_LOCK_SCRIPTS(jsdc);
    _dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: ");
    JSD_UNLOCK_SCRIPTS(jsdc);
#endif /* JSD_DUMP */

    /* local in case hook gets cleared on another thread */
    JSD_LOCK();
    hook = (jsdscript->flags & JSD_SCRIPT_CALL_DESTROY_HOOK_BIT) ? jsdc->scriptHook : NULL;
    hookData = jsdc->scriptHookData;
    JSD_UNLOCK();

    if( hook )
        hook(jsdc, jsdscript, JS_FALSE, hookData);

    JSD_LOCK_SCRIPTS(jsdc);
    JS_HashTableRemove(jsdc->scriptsTable, (void *)script);
    JSD_UNLOCK_SCRIPTS(jsdc);

#ifdef JSD_DUMP
    JSD_LOCK_SCRIPTS(jsdc);
    _dumpJSDScriptList(jsdc);
    JSD_UNLOCK_SCRIPTS(jsdc);
#endif /* JSD_DUMP */
}                
Example #13
0
void JS_DLL_CALLBACK
jsd_NewScriptHookProc( 
                JSContext   *cx,
                const char  *filename,      /* URL this script loads from */
                uintN       lineno,         /* line where this script starts */
                JSScript    *script,
                JSFunction  *fun,                
                void*       callerdata )
{
    JSDScript* jsdscript = NULL;
    JSDContext* jsdc = (JSDContext*) callerdata;
    JSD_ScriptHookProc      hook;
    void*                   hookData;
    
    JSD_ASSERT_VALID_CONTEXT(jsdc);

    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
        return;
    
#ifdef LIVEWIRE
    if( 1 == lineno )
        jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE );
#endif
    
    JSD_LOCK_SCRIPTS(jsdc);
    jsdscript = _newJSDScript(jsdc, cx, script, fun);
    JSD_UNLOCK_SCRIPTS(jsdc);
    if( ! jsdscript )
        return;

#ifdef JSD_DUMP
    JSD_LOCK_SCRIPTS(jsdc);
    _dumpJSDScript(jsdc, jsdscript, "***NEW Script: ");
    _dumpJSDScriptList( jsdc );
    JSD_UNLOCK_SCRIPTS(jsdc);
#endif /* JSD_DUMP */

    /* local in case jsdc->scriptHook gets cleared on another thread */
    JSD_LOCK();
    hook = jsdc->scriptHook;
    hookData = jsdc->scriptHookData;
    JSD_UNLOCK();

    if( hook )
        hook(jsdc, jsdscript, JS_TRUE, hookData);
}                
Example #14
0
void
jsd_NewScriptHookProc( 
                JSContext   *cx,
                const char  *filename,      /* URL this script loads from */
                unsigned       lineno,         /* line where this script starts */
                JSScript    *script,
                JSFunction  *fun,                
                void*       callerdata )
{
    JSDScript* jsdscript = NULL;
    JSDContext* jsdc = (JSDContext*) callerdata;
    JSD_ScriptHookProc      hook;
    void*                   hookData;
    
    JSD_ASSERT_VALID_CONTEXT(jsdc);

    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
        return;
    
    JSD_LOCK_SCRIPTS(jsdc);
    jsdscript = _newJSDScript(jsdc, cx, script);
    JSD_UNLOCK_SCRIPTS(jsdc);
    if( ! jsdscript )
        return;

#ifdef JSD_DUMP
    JSD_LOCK_SCRIPTS(jsdc);
    _dumpJSDScript(jsdc, jsdscript, "***NEW Script: ");
    _dumpJSDScriptList( jsdc );
    JSD_UNLOCK_SCRIPTS(jsdc);
#endif /* JSD_DUMP */

    /* local in case jsdc->scriptHook gets cleared on another thread */
    JSD_LOCK();
    hook = jsdc->scriptHook;
    if( hook )
        jsdscript->flags = jsdscript->flags | JSD_SCRIPT_CALL_DESTROY_HOOK_BIT;
    hookData = jsdc->scriptHookData;
    JSD_UNLOCK();

    if( hook )
        hook(jsdc, jsdscript, JS_TRUE, hookData);
}
Example #15
0
JSBool
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
{
    JSDExecHook* jsdhook;
    JSCList* list = &jsdscript->hooks;

    JSD_LOCK();

    while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
    {
        JS_REMOVE_LINK(&jsdhook->links);
        free(jsdhook);
    }

    JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
    JSD_UNLOCK();

    return JS_TRUE;
}
Example #16
0
JSDContext*
jsd_JSDContextForJSContext(JSContext* context)
{
    JSDContext* iter;
    JSDContext* jsdc = NULL;

    JSD_LOCK();
    for( iter = (JSDContext*)_jsd_context_list.next;
         iter != (JSDContext*)&_jsd_context_list;
         iter = (JSDContext*)iter->links.next )
    {
        if( PR_HashTableLookup(iter->jscontexts, context) )
        {
            jsdc = iter;
            break;
        }
    }
    JSD_UNLOCK();
    return jsdc;
}    
Example #17
0
JSBool
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
{
    JSDExecHook* jsdhook;
    JSCList* list = &jsdscript->hooks;

    JSD_LOCK();

    while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
    {
        JS_REMOVE_LINK(&jsdhook->links);
        free(jsdhook);
    }

    /* No cross-compartment call here because we may be in the middle of GC */
    JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
    JSD_UNLOCK();

    return JS_TRUE;
}
Example #18
0
JSDContext*
jsd_JSDContextForJSContext(JSContext* context)
{
    JSDContext* iter;
    JSDContext* jsdc = NULL;
    JSRuntime*  runtime = JS_GetRuntime(context);

    JSD_LOCK();
    for( iter = (JSDContext*)_jsd_context_list.next;
         iter != (JSDContext*)&_jsd_context_list;
         iter = (JSDContext*)iter->links.next )
    {
        if( runtime == iter->jsrt )
        {
            jsdc = iter;
            break;
        }
    }
    JSD_UNLOCK();
    return jsdc;
}    
Example #19
0
void 
jsd_JSContextUsed(JSDContext* jsdc, JSContext* context)
{
    JSDContextWrapper* wrapper;
    PRHashEntry*       he;

    wrapper = _jsd_JSDContextWrapperForJSContext(jsdc, context);
    if( wrapper )
    {
        /* error reporters are sometimes overwritten by other code... */
        JSErrorReporter oldrep = JS_SetErrorReporter(context, jsd_ErrorReporter);
        if( jsd_ErrorReporter != oldrep )
            wrapper->originalErrorReporter = oldrep;
        return;
    }

    /* else... */
    wrapper = (JSDContextWrapper*) calloc(1,sizeof(JSDContextWrapper));
    if( ! wrapper )
        return;

    JSD_LOCK();
    he = PR_HashTableAdd(jsdc->jscontexts, context, wrapper);
    JSD_UNLOCK();
    if( ! he )
    {
        free(wrapper);
        return;
    }

    wrapper->context = context;
    wrapper->jsdc    = jsdc;

    /* add our error reporter */
    wrapper->originalErrorReporter = JS_SetErrorReporter(context, jsd_ErrorReporter);

    /* add our printer */
    /* add our loader */
}
Example #20
0
JSTrapStatus
jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
                     void *closure)
{
    JSDScript*      jsdscript;
    JSDContext*     jsdc = (JSDContext*) closure;
    JSD_ExecutionHookProc hook;
    void*                 hookData;

    if( ! jsdc || ! jsdc->inited )
        return JSTRAP_CONTINUE;

    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
        return JSTRAP_CONTINUE;

    /* local in case jsdc->interruptHook gets cleared on another thread */
    JSD_LOCK();
    hook     = jsdc->interruptHook;
    hookData = jsdc->interruptHookData;
    JSD_UNLOCK();

    if (!hook)
        return JSTRAP_CONTINUE;
    
    JSD_LOCK_SCRIPTS(jsdc);
    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
    JSD_UNLOCK_SCRIPTS(jsdc);
    if( ! jsdscript )
        return JSTRAP_CONTINUE;

#ifdef LIVEWIRE
    if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (uintptr_t)pc) )
        return JSTRAP_CONTINUE;
#endif

    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
                                 hook, hookData, rval);
}
Example #21
0
static void
_destroyJSDContext(JSDContext* jsdc)
{
    JSD_ASSERT_VALID_CONTEXT(jsdc);

    JSD_LOCK();
    JS_REMOVE_LINK(&jsdc->links);
    JSD_UNLOCK();

    jsd_DestroyObjectManager(jsdc);
    jsd_DestroyAtomTable(jsdc);

    jsdc->inited = JS_FALSE;

    /*
    * We should free jsdc here, but we let it leak in case there are any 
    * asynchronous hooks calling into the system using it as a handle
    *
    * XXX we also leak the locks
    */
    JS_DestroyContext(jsdc->dumbContext);
    jsdc->dumbContext = NULL;
}
Example #22
0
static JSDContext*
_newJSDContext(JSTaskState*       jstaskstate, 
               JSD_UserCallbacks* callbacks, 
               void*              user)
{
    JSDContext* jsdc = NULL;

    if( ! jstaskstate )
        return NULL;

    if( ! _validateUserCallbacks(callbacks) )
        return NULL;

    jsdc = (JSDContext*) calloc(1, sizeof(JSDContext));
    if( ! jsdc )
        goto label_newJSDContext_failure;

    if( ! JSD_INIT_LOCKS(jsdc) )
        goto label_newJSDContext_failure;

    PR_INIT_CLIST(&jsdc->links);

    jsdc->jstaskstate = jstaskstate;

    if( callbacks )
        memcpy(&jsdc->userCallbacks, callbacks, callbacks->size);
    
    jsdc->user = user;

#ifdef JSD_HAS_DANGEROUS_THREAD
    jsdc->dangerousThread = _dangerousThread;
#endif

    PR_INIT_CLIST(&jsdc->threadsStates);
    PR_INIT_CLIST(&jsdc->scripts);
    PR_INIT_CLIST(&jsdc->sources);
    PR_INIT_CLIST(&jsdc->removedSources);

    jsdc->sourceAlterCount = 1;

    jsdc->jscontexts = PR_NewHashTable(256, _hash_root,
                                       PR_CompareValues, PR_CompareValues,
                                       NULL, NULL);
    if( ! jsdc->jscontexts )
        goto label_newJSDContext_failure;

    jsdc->dumbContext = JS_NewContext(jsdc->jstaskstate, 256);
    if( ! jsdc->dumbContext )
        goto label_newJSDContext_failure;

    jsdc->glob = JS_NewObject(jsdc->dumbContext, &global_class, NULL, NULL);
    if( ! jsdc->glob )
        goto label_newJSDContext_failure;

    if( ! JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob) )
        goto label_newJSDContext_failure;

    jsdc->inited = JS_TRUE;

    JSD_LOCK();
    PR_INSERT_LINK(&jsdc->links, &_jsd_context_list);
    JSD_UNLOCK();

    return jsdc;

label_newJSDContext_failure:
    if( jsdc )
        free(jsdc);
    return NULL;
}
Example #23
0
static JSDContext*
_newJSDContext(JSRuntime*         jsrt, 
               JSD_UserCallbacks* callbacks, 
               void*              user,
               JSObject*          scopeobj)
{
    JSDContext* jsdc = NULL;
    JSCrossCompartmentCall *call = NULL;
    JSBool ok;

    if( ! jsrt )
        return NULL;

    if( ! _validateUserCallbacks(callbacks) )
        return NULL;

    jsdc = (JSDContext*) calloc(1, sizeof(JSDContext));
    if( ! jsdc )
        goto label_newJSDContext_failure;

    if( ! JSD_INIT_LOCKS(jsdc) )
        goto label_newJSDContext_failure;

    JS_INIT_CLIST(&jsdc->links);

    jsdc->jsrt = jsrt;

    if( callbacks )
        memcpy(&jsdc->userCallbacks, callbacks, callbacks->size);
    
    jsdc->user = user;

#ifdef JSD_HAS_DANGEROUS_THREAD
    jsdc->dangerousThread = _dangerousThread;
#endif

    JS_INIT_CLIST(&jsdc->threadsStates);
    JS_INIT_CLIST(&jsdc->sources);
    JS_INIT_CLIST(&jsdc->removedSources);

    jsdc->sourceAlterCount = 1;

    if( ! jsd_CreateAtomTable(jsdc) )
        goto label_newJSDContext_failure;

    if( ! jsd_InitObjectManager(jsdc) )
        goto label_newJSDContext_failure;

    if( ! jsd_InitScriptManager(jsdc) )
        goto label_newJSDContext_failure;

    jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256);
    if( ! jsdc->dumbContext )
        goto label_newJSDContext_failure;

    JS_BeginRequest(jsdc->dumbContext);
    JS_SetOptions(jsdc->dumbContext, JS_GetOptions(jsdc->dumbContext) | JSOPTION_ALLOW_XML);

    jsdc->glob = JS_NewCompartmentAndGlobalObject(jsdc->dumbContext, &global_class, NULL);

    if( ! jsdc->glob )
        goto label_newJSDContext_failure;

    call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
    if( ! call )
        goto label_newJSDContext_failure;

    if ( ! JS_AddNamedObjectRoot(jsdc->dumbContext, &jsdc->glob, "JSD context global") )
        goto label_newJSDContext_failure;

    ok = JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob);

    JS_LeaveCrossCompartmentCall(call);
    if( ! ok )
        goto label_newJSDContext_failure;

    JS_EndRequest(jsdc->dumbContext);

    jsdc->data = NULL;
    jsdc->inited = JS_TRUE;

    JSD_LOCK();
    JS_INSERT_LINK(&jsdc->links, &_jsd_context_list);
    JSD_UNLOCK();

    return jsdc;

label_newJSDContext_failure:
    if( jsdc ) {
        if ( jsdc->dumbContext && jsdc->glob )
            JS_RemoveObjectRootRT(JS_GetRuntime(jsdc->dumbContext), &jsdc->glob);
        jsd_DestroyObjectManager(jsdc);
        jsd_DestroyAtomTable(jsdc);
        if( jsdc->dumbContext )
            JS_EndRequest(jsdc->dumbContext);
        free(jsdc);
    }
    return NULL;
}
Example #24
0
jsd_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
    JSDContextWrapper* wrapper;
    JSDContext* jsdc;
    uintN action = JSD_ERROR_REPORTER_PASS_ALONG;
    JSD_ErrorReporter errorReporter;
    void*             errorReporterData;

    jsdc = jsd_JSDContextForJSContext(cx);
    if( ! jsdc )
    {
        PR_ASSERT(0);
        return;
    }

    wrapper = _jsd_JSDContextWrapperForJSContext(jsdc, cx);
    if( ! wrapper )
    {
        PR_ASSERT(0);
        return;
    }

    /* local in case hook gets cleared on another thread */
    JSD_LOCK();
    errorReporter     = jsdc->errorReporter;
    errorReporterData = jsdc->errorReporterData;
    JSD_UNLOCK();

    if( errorReporter && ! JSD_IS_DANGEROUS_THREAD(jsdc) )
        action = errorReporter(jsdc, cx, message, report, 
                               errorReporterData);

    switch(action)
    {
        case JSD_ERROR_REPORTER_PASS_ALONG:
            if( wrapper->originalErrorReporter )
                wrapper->originalErrorReporter(cx, message, report);
            break;
        case JSD_ERROR_REPORTER_RETURN:    
            break;
        case JSD_ERROR_REPORTER_DEBUG:
        {
            JSDThreadState* jsdthreadstate;

            jsdthreadstate = jsd_NewThreadState(jsdc,cx);
            if( jsdthreadstate )
            {
                JSD_ExecutionHookProc   hook;
                void*                   hookData;

                /* local in case hook gets cleared on another thread */
                JSD_LOCK();
                hook = jsdc->debugBreakHook;
                hookData = jsdc->debugBreakHookData;
                JSD_UNLOCK();

                if(hook)
                    hook(jsdc, jsdthreadstate, 
                         JSD_HOOK_DEBUG_REQUESTED, hookData);

                jsd_DestroyThreadState(jsdc, jsdthreadstate);
            }
            break;
        }
        default:
            PR_ASSERT(0);
            break;
    }
}
Example #25
0
JSBool
jsd_SetExecutionHook(JSDContext*           jsdc, 
                     JSDScript*            jsdscript,
                     uintptr_t             pc,
                     JSD_ExecutionHookProc hook,
                     void*                 callerdata)
{
    JSDExecHook* jsdhook;
    JSBool rv;
    JSCrossCompartmentCall *call;

    JSD_LOCK();
    if( ! hook )
    {
        jsd_ClearExecutionHook(jsdc, jsdscript, pc);
        JSD_UNLOCK();
        return JS_TRUE;
    }

    jsdhook = _findHook(jsdc, jsdscript, pc);
    if( jsdhook )
    {
        jsdhook->hook       = hook;
        jsdhook->callerdata = callerdata;
        JSD_UNLOCK();
        return JS_TRUE;
    }
    /* else... */

    jsdhook = (JSDExecHook*)calloc(1, sizeof(JSDExecHook));
    if( ! jsdhook ) {
        JSD_UNLOCK();
        return JS_FALSE;
    }
    jsdhook->jsdscript  = jsdscript;
    jsdhook->pc         = pc;
    jsdhook->hook       = hook;
    jsdhook->callerdata = callerdata;

    call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
    if(!call) {
        free(jsdhook);
        JSD_UNLOCK();
        return JS_FALSE;
    }

    rv = JS_SetTrap(jsdc->dumbContext, jsdscript->script, 
                    (jsbytecode*)pc, jsd_TrapHandler,
                    PRIVATE_TO_JSVAL(jsdhook));

    JS_LeaveCrossCompartmentCall(call);

    if ( ! rv ) {
        free(jsdhook);
        JSD_UNLOCK();
        return JS_FALSE;
    }

    JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
    JSD_UNLOCK();

    return JS_TRUE;
}