JSString* jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JSExceptionState* exceptionState; JSCrossCompartmentCall *call = NULL; jsval stringval; JSString *string; JSBool needWrap; JSObject *scopeObj; if(jsdval->string) return jsdval->string; /* Reuse the string without copying or re-rooting it */ if(JSVAL_IS_STRING(jsdval->val)) { jsdval->string = JSVAL_TO_STRING(jsdval->val); return jsdval->string; } JS_BeginRequest(cx); /* Objects call JS_ValueToString in their own compartment. */ scopeObj = JSVAL_IS_OBJECT(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob; call = JS_EnterCrossCompartmentCall(cx, scopeObj); if(!call) { JS_EndRequest(cx); return NULL; } exceptionState = JS_SaveExceptionState(cx); string = JS_ValueToString(cx, jsdval->val); JS_RestoreExceptionState(cx, exceptionState); JS_LeaveCrossCompartmentCall(call); call = NULL; if(string) { stringval = STRING_TO_JSVAL(string); call = JS_EnterCrossCompartmentCall(cx, jsdc->glob); } if(!string || !call || !JS_WrapValue(cx, &stringval)) { if(call) JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); return NULL; } jsdval->string = JSVAL_TO_STRING(stringval); if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString")) jsdval->string = NULL; JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); return jsdval->string; }
static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JSObject *obj; JSPropertyDescArray pda; uintN i; JSCrossCompartmentCall *call = NULL; JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props)); JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS))); JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val)); if(JSVAL_IS_PRIMITIVE(jsdval->val)) return JS_FALSE; obj = JSVAL_TO_OBJECT(jsdval->val); JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if(!call) { JS_EndRequest(jsdc->dumbContext); return JS_FALSE; } if(!JS_GetPropertyDescArray(cx, obj, &pda)) { JS_EndRequest(cx); JS_LeaveCrossCompartmentCall(call); return JS_FALSE; } for(i = 0; i < pda.length; i++) { JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0); if(!prop) { _freeProps(jsdc, jsdval); break; } JS_APPEND_LINK(&prop->links, &jsdval->props); } JS_PutPropertyDescArray(cx, &pda); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); SET_BIT_FLAG(jsdval->flags, GOT_PROPS); return !JS_CLIST_IS_EMPTY(&jsdval->props); }
JSString* jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JSFunction* fun; JSExceptionState* exceptionState; JSCrossCompartmentCall *call = NULL; if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval)) { JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val)); if(!call) { JS_EndRequest(cx); return NULL; } exceptionState = JS_SaveExceptionState(cx); fun = JSD_GetValueFunction(jsdc, jsdval); JS_RestoreExceptionState(cx, exceptionState); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); if(!fun) return NULL; jsdval->funName = JS_GetFunctionId(fun); /* For compatibility we return "anonymous", not an empty string here. */ if (!jsdval->funName) jsdval->funName = JS_GetAnonymousString(jsdc->jsrt); } return jsdval->funName; }
uintptr_t jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, unsigned line) { uintptr_t pc; JSCrossCompartmentCall *call; if( !jsdscript ) return 0; #ifdef LIVEWIRE if( jsdscript->lwscript ) { unsigned newline; jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline); if( line != newline ) line = newline; } #endif call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if(!call) return 0; pc = (uintptr_t) JS_LineNumberToPC(jsdc->dumbContext, jsdscript->script, line ); JS_LeaveCrossCompartmentCall(call); return pc; }
void jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JSCrossCompartmentCall *call = NULL; if(jsdval->string) { /* if the jsval is a string, then we didn't need to root the string */ if(!JSVAL_IS_STRING(jsdval->val)) { JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(cx, jsdc->glob); if(!call) { JS_EndRequest(cx); return; } JS_RemoveStringRoot(cx, &jsdval->string); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); } jsdval->string = NULL; } jsdval->funName = NULL; jsdval->className = NULL; DROP_CLEAR_VALUE(jsdc, jsdval->proto); DROP_CLEAR_VALUE(jsdc, jsdval->parent); DROP_CLEAR_VALUE(jsdc, jsdval->ctor); _freeProps(jsdc, jsdval); jsdval->flags = 0; }
JSBool jsd_ClearExecutionHook(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc) { JSCrossCompartmentCall *call; JSDExecHook* jsdhook; JSD_LOCK(); jsdhook = _findHook(jsdc, jsdscript, pc); if( ! jsdhook ) { JSD_UNLOCK(); return JS_FALSE; } call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if(!call) { JSD_UNLOCK(); return JS_FALSE; } JS_ClearTrap(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc, NULL, NULL ); JS_LeaveCrossCompartmentCall(call); JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); JSD_UNLOCK(); return JS_TRUE; }
JSDValue* jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval) { JSCrossCompartmentCall *call = NULL; if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO))) { JSObject* obj; JSObject* proto; JS_ASSERT(!jsdval->proto); SET_BIT_FLAG(jsdval->flags, GOT_PROTO); if(!JSVAL_IS_OBJECT(jsdval->val)) return NULL; if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if(!call) { JS_EndRequest(jsdc->dumbContext); return NULL; } proto = JS_GetPrototype(jsdc->dumbContext, obj); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); if(!proto) return NULL; jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto)); } if(jsdval->proto) jsdval->proto->nref++; return jsdval->proto; }
unsigned jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc) { JSCrossCompartmentCall *call; unsigned first = jsdscript->lineBase; unsigned last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1; unsigned line = 0; call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if(!call) return 0; if (pc) line = JS_PCToLineNumber(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc); JS_LeaveCrossCompartmentCall(call); if( line < first ) return first; if( line > last ) return last; #ifdef LIVEWIRE if( jsdscript && jsdscript->lwscript ) { unsigned newline; jsdlw_ProcessedToRawLineNumber(jsdc, jsdscript, line, &newline); line = newline; } #endif return line; }
JSBool jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JSFunction* fun; JSExceptionState* exceptionState; JSCrossCompartmentCall *call = NULL; if(jsd_IsValueFunction(jsdc, jsdval)) { JSBool ok = JS_FALSE; JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val)); if(!call) { JS_EndRequest(cx); return JS_FALSE; } exceptionState = JS_SaveExceptionState(cx); fun = JSD_GetValueFunction(jsdc, jsdval); JS_RestoreExceptionState(cx, exceptionState); if(fun) ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE; JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); JS_ASSERT(fun); return ok; } return !JSVAL_IS_PRIMITIVE(jsdval->val); }
ScriptInterface_impl::~ScriptInterface_impl() { if (m_call) JS_LeaveCrossCompartmentCall(m_call); JS_EndRequest(m_cx); JS_DestroyContext(m_cx); }
JSDValue* jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval) { JSCrossCompartmentCall *call = NULL; if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT))) { JSObject* obj; JSObject* parent; JS_ASSERT(!jsdval->parent); SET_BIT_FLAG(jsdval->flags, GOT_PARENT); if(!JSVAL_IS_OBJECT(jsdval->val)) return NULL; if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if(!call) { JS_EndRequest(jsdc->dumbContext); return NULL; } parent = JS_GetParent(jsdc->dumbContext,obj); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); if(!parent) return NULL; jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent)); } if(jsdval->parent) jsdval->parent->nref++; return jsdval->parent; }
const char* jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval) { jsval val = jsdval->val; JSCrossCompartmentCall *call = NULL; if(!jsdval->className && JSVAL_IS_OBJECT(val)) { JSObject* obj; if(!(obj = JSVAL_TO_OBJECT(val))) return NULL; JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if(!call) { JS_EndRequest(jsdc->dumbContext); return NULL; } if(JS_GET_CLASS(jsdc->dumbContext, obj)) jsdval->className = JS_GET_CLASS(jsdc->dumbContext, obj)->name; JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); } return jsdval->className; }
void jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval) { JSCrossCompartmentCall *call = NULL; JS_ASSERT(jsdval->nref > 0); if(0 == --jsdval->nref) { jsd_RefreshValue(jsdc, jsdval); if(JSVAL_IS_GCTHING(jsdval->val)) { JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob); if(!call) { JS_EndRequest(jsdc->dumbContext); return; } JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); } free(jsdval); } }
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; }
/* * Create a new JSD value referring to a jsval. Copy string values into the * JSD compartment. Leave all other GCTHINGs in their native compartments * and access them through cross-compartment calls. */ JSDValue* jsd_NewValue(JSDContext* jsdc, jsval val) { JSDValue* jsdval; JSCrossCompartmentCall *call = NULL; if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue)))) return NULL; if(JSVAL_IS_GCTHING(val)) { JSBool ok; JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob); if(!call) { JS_EndRequest(jsdc->dumbContext); free(jsdval); return NULL; } ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue"); if(ok && JSVAL_IS_STRING(val)) { if(!JS_WrapValue(jsdc->dumbContext, &val)) { ok = JS_FALSE; } } JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); if(!ok) { free(jsdval); return NULL; } } jsdval->val = val; jsdval->nref = 1; JS_INIT_CLIST(&jsdval->props); return jsdval; }
/* * Retrieve a JSFunction* from a JSDValue*. This differs from * JS_ValueToFunction by fully unwrapping the object first. */ JSFunction* jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval) { JSObject *obj; JSFunction *fun; JSCrossCompartmentCall *call = NULL; if (!JSVAL_IS_OBJECT(jsdval->val)) return NULL; if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; obj = JS_UnwrapObject(obj); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if (!call) return NULL; fun = JS_ValueToFunction(jsdc->dumbContext, OBJECT_TO_JSVAL(obj)); JS_LeaveCrossCompartmentCall(call); return fun; }
JSDScript* jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; jsval val = jsdval->val; JSFunction* fun = NULL; JSExceptionState* exceptionState; JSScript* script = NULL; JSDScript* jsdscript; JSCrossCompartmentCall *call = NULL; if (!jsd_IsValueFunction(jsdc, jsdval)) return NULL; JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val)); if (!call) { JS_EndRequest(cx); return NULL; } exceptionState = JS_SaveExceptionState(cx); fun = JSD_GetValueFunction(jsdc, jsdval); JS_RestoreExceptionState(cx, exceptionState); if (fun) script = JS_GetFunctionScript(cx, fun); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); if (!script) return NULL; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); return jsdscript; }
JSDValue* jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval) { JSCrossCompartmentCall *call = NULL; if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR))) { JSObject* obj; JSObject* proto; JSObject* ctor; JS_ASSERT(!jsdval->ctor); SET_BIT_FLAG(jsdval->flags, GOT_CTOR); if(!JSVAL_IS_OBJECT(jsdval->val)) return NULL; if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; proto = JS_GetPrototype(obj); if(!proto) return NULL; JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if(!call) { JS_EndRequest(jsdc->dumbContext); return NULL; } ctor = JS_GetConstructor(jsdc->dumbContext,proto); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); if(!ctor) return NULL; jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor)); } if(jsdval->ctor) jsdval->ctor->nref++; return jsdval->ctor; }
JSBool jsd_GetLinePCs(JSDContext* jsdc, JSDScript* jsdscript, unsigned startLine, unsigned maxLines, unsigned* count, unsigned** retLines, uintptr_t** retPCs) { JSCrossCompartmentCall *call; unsigned first = jsdscript->lineBase; unsigned last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1; JSBool ok; unsigned *lines; jsbytecode **pcs; unsigned i; if (last < startLine) return JS_TRUE; call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if (!call) return JS_FALSE; ok = JS_GetLinePCs(jsdc->dumbContext, jsdscript->script, startLine, maxLines, count, retLines, &pcs); if (ok) { if (retPCs) { for (i = 0; i < *count; ++i) { (*retPCs)[i] = (*pcs)[i]; } } JS_free(jsdc->dumbContext, pcs); } JS_LeaveCrossCompartmentCall(call); return ok; }
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; }
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; }
JSDProperty* jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name) { JSContext* cx = jsdc->dumbContext; JSDProperty* jsdprop; JSDProperty* iter = NULL; JSObject* obj; uintN attrs = 0; JSBool found; JSPropertyDesc pd; const jschar * nameChars; size_t nameLen; jsval val, nameval; jsid nameid; JSCrossCompartmentCall *call = NULL; if(!jsd_IsValueObject(jsdc, jsdval)) return NULL; /* If we already have the prop, then return it */ while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter))) { JSString* propName = jsd_GetValueString(jsdc, jsdprop->name); if(propName) { intN result; if (JS_CompareStrings(cx, propName, name, &result) && !result) return jsdprop; } JSD_DropProperty(jsdc, jsdprop); } /* Not found in property list, look it up explicitly */ if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen))) return NULL; JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(cx, obj); if(!call) { JS_EndRequest(cx); return NULL; } JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found); if (!found) { JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); return NULL; } JS_ClearPendingException(cx); if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val)) { if (JS_IsExceptionPending(cx)) { if (!JS_GetPendingException(cx, &pd.value)) { JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); return NULL; } pd.flags = JSPD_EXCEPTION; } else { pd.flags = JSPD_ERROR; pd.value = JSVAL_VOID; } } else { pd.value = val; } JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); nameval = STRING_TO_JSVAL(name); if (!JS_ValueToId(cx, nameval, &nameid) || !JS_IdToValue(cx, nameid, &pd.id)) { return NULL; } pd.slot = pd.spare = 0; pd.alias = JSVAL_NULL; pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0 | (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0 | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0; return _newProperty(jsdc, &pd, JSDPD_HINTED); }