void js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval) { #if JS_HAS_VALUEOF_HINT jsval argv[1]; argv[0] = ATOM_KEY(cx->runtime->atomState.typeAtoms[type]); js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 1, argv, rval); #else js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 0, NULL, rval); #endif }
JSString * js_ObjectToString(JSContext *cx, JSObject *obj) { jsval v, *mark, *argv; JSString *str; if (!obj) return ATOM_TO_STRING(cx->runtime->atomState.nullAtom); v = JSVAL_VOID; if (!obj->map->clasp->convert(cx, obj, JSTYPE_STRING, &v)) return NULL; if (JSVAL_IS_STRING(v)) return JSVAL_TO_STRING(v); /* Try the toString method if it's defined. */ js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0, NULL, &v); if (JSVAL_IS_STRING(v)) return JSVAL_TO_STRING(v); #if JS_BUG_EAGER_TOSTRING js_TryValueOf(cx, obj, JSTYPE_STRING, &v); if (JSVAL_IS_STRING(v)) return JSVAL_TO_STRING(v); #endif mark = PR_ARENA_MARK(&cx->stackPool); PR_ARENA_ALLOCATE(argv, &cx->stackPool, OBJ_TOSTRING_NARGS * sizeof(jsval)); if (!argv || !js_obj_toString(cx, obj, OBJ_TOSTRING_NARGS, argv, &v)) str = NULL; else str = JSVAL_TO_STRING(v); PR_ARENA_RELEASE(&cx->stackPool, mark); return str; }
JSBool js_TryJSON(JSContext *cx, jsval *vp) { // Checks whether the return value implements toJSON() JSBool ok = JS_TRUE; if (!JSVAL_IS_PRIMITIVE(*vp)) { JSObject *obj = JSVAL_TO_OBJECT(*vp); ok = js_TryMethod(cx, obj, cx->runtime->atomState.toJSONAtom, 0, NULL, vp); } return ok; }
static JSBool array_join_sub(JSContext *cx, JSObject *obj, JSString *sep, JSBool literalize, jsval *rval, JSBool localeString) { JSBool ok; jsval v; jsuint length, index; jschar *chars, *ochars; size_t nchars, growth, seplen, tmplen; const jschar *sepstr; JSString *str; JSHashEntry *he; JSObject *obj2; ok = js_GetLengthProperty(cx, obj, &length); if (!ok) return JS_FALSE; he = js_EnterSharpObject(cx, obj, NULL, &chars); if (!he) return JS_FALSE; if (literalize) { if (IS_SHARP(he)) { #if JS_HAS_SHARP_VARS nchars = js_strlen(chars); #else chars[0] = '['; chars[1] = ']'; chars[2] = 0; nchars = 2; #endif goto make_string; } /* * Allocate 1 + 3 + 1 for "[", the worst-case closing ", ]", and the * terminating 0. */ growth = (1 + 3 + 1) * sizeof(jschar); if (!chars) { nchars = 0; chars = (jschar *) malloc(growth); if (!chars) goto done; } else { MAKE_SHARP(he); nchars = js_strlen(chars); chars = (jschar *) realloc((ochars = chars), nchars * sizeof(jschar) + growth); if (!chars) { free(ochars); goto done; } } chars[nchars++] = '['; } else { /* * Free any sharp variable definition in chars. Normally, we would * MAKE_SHARP(he) so that only the first sharp variable annotation is * a definition, and all the rest are references, but in the current * case of (!literalize), we don't need chars at all. */ if (chars) JS_free(cx, chars); chars = NULL; nchars = 0; /* Return the empty string on a cycle as well as on empty join. */ if (IS_BUSY(he) || length == 0) { js_LeaveSharpObject(cx, NULL); *rval = JS_GetEmptyStringValue(cx); return ok; } /* Flag he as BUSY so we can distinguish a cycle from a join-point. */ MAKE_BUSY(he); } sepstr = NULL; seplen = JSSTRING_LENGTH(sep); v = JSVAL_NULL; for (index = 0; index < length; index++) { ok = JS_GetElement(cx, obj, index, &v); if (!ok) goto done; if (!literalize && (JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))) { str = cx->runtime->emptyString; } else { if (localeString) { if (!js_ValueToObject(cx, v, &obj2) || !js_TryMethod(cx, obj2, cx->runtime->atomState.toLocaleStringAtom, 0, NULL, &v)) { str = NULL; } else { str = js_ValueToString(cx, v); } } else { str = (literalize ? js_ValueToSource : js_ValueToString)(cx, v); } if (!str) { ok = JS_FALSE; goto done; } } /* Allocate 3 + 1 at end for ", ", closing bracket, and zero. */ growth = (nchars + (sepstr ? seplen : 0) + JSSTRING_LENGTH(str) + 3 + 1) * sizeof(jschar); if (!chars) { chars = (jschar *) malloc(growth); if (!chars) goto done; } else { chars = (jschar *) realloc((ochars = chars), growth); if (!chars) { free(ochars); goto done; } } if (sepstr) { js_strncpy(&chars[nchars], sepstr, seplen); nchars += seplen; } sepstr = JSSTRING_CHARS(sep); tmplen = JSSTRING_LENGTH(str); js_strncpy(&chars[nchars], JSSTRING_CHARS(str), tmplen); nchars += tmplen; } done: if (literalize) { if (chars) { if (JSVAL_IS_VOID(v)) { chars[nchars++] = ','; chars[nchars++] = ' '; } chars[nchars++] = ']'; } } else { CLEAR_BUSY(he); } js_LeaveSharpObject(cx, NULL); if (!ok) { if (chars) free(chars); return ok; } make_string: if (!chars) { JS_ReportOutOfMemory(cx); return JS_FALSE; } chars[nchars] = 0; str = js_NewString(cx, chars, nchars, 0); if (!str) { free(chars); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); return JS_TRUE; }