bool CoerceDouble(const JS::Value& v, double* d) { if (v.isDouble()) { *d = v.toDouble(); } else if (v.isInt32()) { *d = double(v.toInt32()); } else if (v.isUndefined()) { *d = 0.0; } else { return false; } return true; }
std::string gjs_debug_value(JS::Value v) { std::ostringstream out; if (v.isNull()) return "null"; if (v.isUndefined()) return "undefined"; if (v.isInt32()) { out << v.toInt32(); return out.str(); } if (v.isDouble()) { out << v.toDouble(); return out.str(); } if (v.isString()) { out << gjs_debug_string(v.toString()); return out.str(); } if (v.isSymbol()) { out << gjs_debug_symbol(v.toSymbol()); return out.str(); } if (v.isObject() && js::IsFunctionObject(&v.toObject())) { JSFunction* fun = JS_GetObjectFunction(&v.toObject()); JSString *display_name = JS_GetFunctionDisplayId(fun); if (display_name) out << "<function " << gjs_debug_string(display_name); else out << "<unnamed function"; out << " at " << fun << '>'; return out.str(); } if (v.isObject()) { out << gjs_debug_object(&v.toObject()); return out.str(); } if (v.isBoolean()) return (v.toBoolean() ? "true" : "false"); if (v.isMagic()) return "<magic>"; return "unexpected value"; }
/*! @brief Fill a bottle with the contents of an object. @param[in] jct The %JavaScript engine context. @param[in,out] aBottle The bottle to be filled. @param[in] theData The value to be sent. @param[in] topLevel @c true if this is the outermost list of an object. */ static void fillBottleFromValue(JSContext * jct, yarp::os::Bottle & aBottle, JS::Value theData, const bool topLevel) { ODL_ENTER(); //#### ODL_P2("jct = ", jct, "aBottle = ", &aBottle); //#### ODL_B1("topLevel = ", topLevel); //#### JS::RootedValue asRootedValue(jct); asRootedValue = theData; if (theData.isBoolean()) { aBottle.addInt(JS::ToBoolean(asRootedValue) ? 1 : 0); } else if (theData.isDouble()) { double aValue; if (JS::ToNumber(jct, asRootedValue, &aValue)) { aBottle.addDouble(aValue); } } else if (theData.isInt32()) { int32_t aValue; if (JS::ToInt32(jct, asRootedValue, &aValue)) { aBottle.addInt(aValue); } } else if (theData.isString()) { JSString * asString = theData.toString(); char * asChars = JS_EncodeString(jct, asString); aBottle.addString(asChars); JS_free(jct, asChars); } else if (theData.isObject()) { JS::RootedObject asObject(jct); if (JS_ValueToObject(jct, asRootedValue, &asObject)) { bool processed = false; #if (47 <= MOZJS_MAJOR_VERSION) bool isArray; #endif // 47 <= MOZJS_MAJOR_VERSION #if (47 <= MOZJS_MAJOR_VERSION) if (JS_IsArrayObject(jct, asObject, &isArray)) #else // 47 > MOZJS_MAJOR_VERSION if (JS_IsArrayObject(jct, asObject)) #endif // 47 > MOZJS_MAJOR_VERSION { uint32_t arrayLength; if (JS_GetArrayLength(jct, asObject, &arrayLength)) { // Treat as a list if (topLevel) { for (uint32_t ii = 0; arrayLength > ii; ++ii) { JS::RootedValue anElement(jct); if (JS_GetElement(jct, asObject, ii, &anElement)) { fillBottleFromValue(jct, aBottle, anElement, false); } } } else { yarp::os::Bottle & innerList(aBottle.addList()); for (uint32_t ii = 0; arrayLength > ii; ++ii) { JS::RootedValue anElement(jct); if (JS_GetElement(jct, asObject, ii, &anElement)) { fillBottleFromValue(jct, innerList, anElement, false); } } } processed = true; } } if (! processed) { // Treat as a dictionary yarp::os::Property & innerDict(aBottle.addDict()); #if (47 <= MOZJS_MAJOR_VERSION) JS::Rooted<JS::IdVector> ids(jct, JS::IdVector(jct)); #else // 47 > MOZJS_MAJOR_VERSION JS::AutoIdArray ids(jct, JS_Enumerate(jct, asObject)); #endif // 47 > MOZJS_MAJOR_VERSION #if (47 <= MOZJS_MAJOR_VERSION) if (JS_Enumerate(jct, asObject, &ids)) #else // 47 > MOZJS_MAJOR_VERSION // Note that only operator! is defined, so we need to do a 'double-negative'. if (!! ids) #endif // 47 > MOZJS_MAJOR_VERSION { for (size_t ii = 0, len = ids.length(); len > ii; ++ii) { JS::RootedValue key(jct); if (JS_IdToValue(jct, ids[ii], &key)) { JS::RootedValue key(jct); JS::RootedValue result(jct); JS::RootedId aRootedId(jct); aRootedId = ids[ii]; if (JS_IdToValue(jct, ids[ii], &key) && JS_GetPropertyById(jct, asObject, aRootedId, &result)) { JSString * keyString = key.toString(); char * keyAsChars = JS_EncodeString(jct, keyString); YarpString keyToUse(keyAsChars); yarp::os::Bottle convertedResult; JS_free(jct, keyAsChars); fillBottleFromValue(jct, convertedResult, result, false); if (1 == convertedResult.size()) { yarp::os::Value anElement(convertedResult.get(0)); if (anElement.isInt()) { innerDict.put(keyToUse, anElement.asInt()); } else if (anElement.isDouble()) { innerDict.put(keyToUse, anElement.asDouble()); } else if (anElement.isString()) { innerDict.put(keyToUse, anElement.asString()); } else { innerDict.put(keyToUse, anElement); } } } } } } } } } ODL_EXIT(); //#### } // fillBottleFromValue