nsresult nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue, nsJSONWriter* writer) { JSAutoRequest ar(cx); // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (!aValue.isObject()) { return NS_ERROR_INVALID_ARG; } JSObject* obj = &aValue.toObject(); JS::Value val = aValue; /* Backward compatibility: * Manually call toJSON if implemented by the object and check that * the result is still an object * Note: It is perfectly fine to not implement toJSON, so it is * perfectly fine for GetMethod to fail */ JS::Value toJSON; if (JS_GetMethod(cx, obj, "toJSON", NULL, &toJSON) && !JSVAL_IS_PRIMITIVE(toJSON) && JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(toJSON))) { // If toJSON is implemented, it must not throw if (!JS_CallFunctionValue(cx, obj, toJSON, 0, NULL, &val)) { if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // No exception, but still failed return NS_ERROR_FAILURE; } // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (JSVAL_IS_PRIMITIVE(val)) return NS_ERROR_INVALID_ARG; } // GetMethod may have thrown else if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // Backward compatibility: // function shall not pass, just "plain" objects and arrays JSType type = JS_TypeOfValue(cx, val); if (type == JSTYPE_FUNCTION) return NS_ERROR_INVALID_ARG; // We're good now; try to stringify if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, WriteCallback, writer)) return NS_ERROR_FAILURE; return NS_OK; }
nsresult nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue, nsJSONWriter* writer) { // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (!aValue.isObject()) { return NS_ERROR_INVALID_ARG; } JS::Rooted<JSObject*> obj(cx, &aValue.toObject()); /* Backward compatibility: * Manually call toJSON if implemented by the object and check that * the result is still an object * Note: It is perfectly fine to not implement toJSON, so it is * perfectly fine for GetMethod to fail */ JS::Rooted<JS::Value> val(cx, aValue); JS::Rooted<JS::Value> toJSON(cx); if (JS_GetProperty(cx, obj, "toJSON", &toJSON) && toJSON.isObject() && JS_ObjectIsCallable(cx, &toJSON.toObject())) { // If toJSON is implemented, it must not throw if (!JS_CallFunctionValue(cx, obj, toJSON, 0, nullptr, val.address())) { if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // No exception, but still failed return NS_ERROR_FAILURE; } // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (val.isPrimitive()) return NS_ERROR_INVALID_ARG; } // GetMethod may have thrown else if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // Backward compatibility: // function shall not pass, just "plain" objects and arrays JSType type = JS_TypeOfValue(cx, val); if (type == JSTYPE_FUNCTION) return NS_ERROR_INVALID_ARG; // We're good now; try to stringify if (!JS_Stringify(cx, &val, JS::NullPtr(), JS::NullHandleValue, WriteCallback, writer)) return NS_ERROR_FAILURE; return NS_OK; }
bool CallbackInterface::GetCallableProperty(JSContext* cx, const char* aPropName, JS::MutableHandle<JS::Value> aCallable) { if (!JS_GetProperty(cx, mCallback, aPropName, aCallable.address())) { return false; } if (!aCallable.isObject() || !JS_ObjectIsCallable(cx, &aCallable.toObject())) { nsPrintfCString description("Property '%s'", aPropName); ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get()); return false; } return true; }
bool CallbackInterface::GetCallableProperty(JSContext* cx, JS::Handle<jsid> aPropId, JS::MutableHandle<JS::Value> aCallable) { if (!JS_GetPropertyById(cx, CallbackPreserveColor(), aPropId, aCallable)) { return false; } if (!aCallable.isObject() || !JS_ObjectIsCallable(cx, &aCallable.toObject())) { char* propName = JS_EncodeString(cx, JS_FORGET_STRING_FLATNESS(JSID_TO_FLAT_STRING(aPropId))); nsPrintfCString description("Property '%s'", propName); JS_free(cx, propName); ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get()); return false; } return true; }
JSBool jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval) { return !JSVAL_IS_PRIMITIVE(jsdval->val) && JS_ObjectIsCallable(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val)); }