static JSBool math_pow(JSContext *cx, uintN argc, jsval *vp) { jsdouble x, y, z; if (argc <= 1) { *vp = cx->runtime->NaNValue; return JS_TRUE; } x = js_ValueToNumber(cx, &vp[2]); if (JSVAL_IS_NULL(vp[2])) return JS_FALSE; y = js_ValueToNumber(cx, &vp[3]); if (JSVAL_IS_NULL(vp[3])) return JS_FALSE; /* * Because C99 and ECMA specify different behavior for pow(), * we need to wrap the libm call to make it ECMA compliant. */ if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) { *vp = cx->runtime->NaNValue; return JS_TRUE; } /* pow(x, +-0) is always 1, even for x = NaN. */ if (y == 0) { *vp = JSVAL_ONE; return JS_TRUE; } z = pow(x, y); return js_NewNumberInRootedValue(cx, z, vp); }
static jsdouble FASTCALL math_pow_tn(jsdouble d, jsdouble p) { if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0)) return js_NaN; if (p == 0) return 1.0; return pow(d, p); }
static JSBool math_pow(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { jsdouble x, y, z; if (!js_ValueToNumber(cx, argv[0], &x)) return JS_FALSE; if (!js_ValueToNumber(cx, argv[1], &y)) return JS_FALSE; #if !JS_USE_FDLIBM_MATH /* * Because C99 and ECMA specify different behavior for pow(), * we need to wrap the libm call to make it ECMA compliant. */ if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) { *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); return JS_TRUE; } #endif z = fd_pow(x, y); return js_NewNumberValue(cx, z, rval); }
JSBool js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, JSONWriteCallback callback, void *data, uint32 depth) { if (depth > JSON_MAX_DEPTH) return JS_FALSE; /* encoding error */ JSBool ok = JS_TRUE; JSObject *obj = JSVAL_TO_OBJECT(*vp); JSBool isArray = JS_IsArrayObject(cx, obj); jschar output = jschar(isArray ? '[' : '{'); if (!callback(&output, 1, data)) return JS_FALSE; JSObject *iterObj = NULL; jsint i = 0; jsuint length = 0; if (isArray) { if (!JS_GetArrayLength(cx, obj, &length)) return JS_FALSE; } else { if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp)) return JS_FALSE; iterObj = JSVAL_TO_OBJECT(*vp); } jsval outputValue = JSVAL_VOID; JSAutoTempValueRooter tvr(cx, 1, &outputValue); jsval key; JSBool memberWritten = JS_FALSE; do { outputValue = JSVAL_VOID; if (isArray) { if ((jsuint)i >= length) break; ok = JS_GetElement(cx, obj, i++, &outputValue); } else { ok = js_CallIteratorNext(cx, iterObj, &key); if (!ok) break; if (key == JSVAL_HOLE) break; JSString *ks; if (JSVAL_IS_STRING(key)) { ks = JSVAL_TO_STRING(key); } else { ks = JS_ValueToString(cx, key); if (!ks) { ok = JS_FALSE; break; } } ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks), JS_GetStringLength(ks), &outputValue); } if (!ok) break; // if this is an array, holes are transmitted as null if (isArray && outputValue == JSVAL_VOID) { outputValue = JSVAL_NULL; } else if (JSVAL_IS_OBJECT(outputValue)) { ok = js_TryJSON(cx, &outputValue); if (!ok) break; } // elide undefined values if (outputValue == JSVAL_VOID) continue; // output a comma unless this is the first member to write if (memberWritten) { output = jschar(','); ok = callback(&output, 1, data); if (!ok) break; } memberWritten = JS_TRUE; JSType type = JS_TypeOfValue(cx, outputValue); // Can't encode these types, so drop them if (type == JSTYPE_FUNCTION || type == JSTYPE_XML) break; // Be careful below, this string is weakly rooted. JSString *s; // If this isn't an array, we need to output a key if (!isArray) { s = JS_ValueToString(cx, key); if (!s) { ok = JS_FALSE; break; } ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s)); if (!ok) break; output = jschar(':'); ok = callback(&output, 1, data); if (!ok) break; } if (!JSVAL_IS_PRIMITIVE(outputValue)) { // recurse ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1); } else { JSString *outputString; s = JS_ValueToString(cx, outputValue); if (!s) { ok = JS_FALSE; break; } if (type == JSTYPE_STRING) { ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s)); if (!ok) break; continue; } if (type == JSTYPE_NUMBER) { if (JSVAL_IS_DOUBLE(outputValue)) { jsdouble d = *JSVAL_TO_DOUBLE(outputValue); if (!JSDOUBLE_IS_FINITE(d)) outputString = JS_NewStringCopyN(cx, "null", 4); else outputString = s; } else { outputString = s; } } else if (type == JSTYPE_BOOLEAN) { outputString = s; } else if (JSVAL_IS_NULL(outputValue)) { outputString = JS_NewStringCopyN(cx, "null", 4); } else { ok = JS_FALSE; // encoding error break; } ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data); } } while (ok); if (iterObj) { // Always close the iterator, but make sure not to stomp on OK js_CloseIteratorState(cx, iterObj); // encoding error or propagate? FIXME: Bug 408838. } if (!ok) { JS_ReportError(cx, "Error during JSON encoding."); return JS_FALSE; } output = jschar(isArray ? ']' : '}'); ok = callback(&output, 1, data); return ok; }