/** Convert a jsval to a string and store it in struct bookmark. * * @param ctx * Context for memory allocations and error reports. * @param val * The @c jsval that should be converted. * @param[in,out] result * A string allocated with mem_alloc(). * On success, this function frees the original string, if any. * * @return JS_TRUE if successful. On error, report the error to * SpiderMonkey and return JS_FALSE. */ static JSBool jsval_to_bookmark_string(JSContext *ctx, jsid id, unsigned char **result) { JSString *jsstr = NULL; unsigned char *str; jsval val; /* jsstring_to_utf8() might GC; protect the string to come. */ if (!JS_AddNamedStringRoot(ctx, &jsstr, "jsval_to_bookmark_string")) return JS_FALSE; if (JS_TRUE != JS_IdToValue(ctx, id, &val)) { JS_RemoveStringRoot(ctx, &jsstr); return JS_FALSE; } jsstr = JS_ValueToString(ctx, val); if (jsstr == NULL) { JS_RemoveStringRoot(ctx, &jsstr); return JS_FALSE; } str = jsstring_to_utf8(ctx, jsstr, NULL); if (str == NULL) { JS_RemoveStringRoot(ctx, &jsstr); return JS_FALSE; } JS_RemoveStringRoot(ctx, &jsstr); mem_free_set(result, str); return JS_TRUE; }
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; }
JSString* jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JSExceptionState* exceptionState; JSCompartment* oldCompartment = NULL; jsval stringval; JS::RootedString string(cx); JS::RootedObject scopeObj(cx); 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_PRIMITIVE(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob; oldCompartment = JS_EnterCompartment(cx, scopeObj); exceptionState = JS_SaveExceptionState(cx); string = JS_ValueToString(cx, jsdval->val); JS_RestoreExceptionState(cx, exceptionState); JS_LeaveCompartment(cx, oldCompartment); oldCompartment = NULL; if(string) { stringval = STRING_TO_JSVAL(string); oldCompartment = JS_EnterCompartment(cx, jsdc->glob); } if(!string || !JS_WrapValue(cx, &stringval)) { if(oldCompartment) JS_LeaveCompartment(cx, oldCompartment); JS_EndRequest(cx); return NULL; } jsdval->string = JSVAL_TO_STRING(stringval); if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString")) jsdval->string = NULL; JS_LeaveCompartment(cx, oldCompartment); JS_EndRequest(cx); return jsdval->string; }