QJsonObject QV8JsonWrapper::toJsonObject(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects) { QJsonObject result; if (!value->IsObject() || value->IsArray() || value->IsFunction()) return result; v8::Handle<v8::Object> v8object(value.As<v8::Object>()); if (visitedObjects.contains(v8object)) { // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty object (and no error is thrown). return result; } visitedObjects.insert(v8object); v8::Local<v8::Array> propertyNames = m_engine->getOwnPropertyNames(v8object); uint32_t length = propertyNames->Length(); for (uint32_t i = 0; i < length; ++i) { v8::Local<v8::Value> name = propertyNames->Get(i); v8::Local<v8::Value> propertyValue = v8object->Get(name); if (!propertyValue->IsFunction()) result.insert(QJSConverter::toString(name->ToString()), toJsonValue(propertyValue, visitedObjects)); } visitedObjects.remove(v8object); return result; }
QJsonArray QV8JsonWrapper::toJsonArray(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects) { QJsonArray result; if (!value->IsArray()) return result; v8::Handle<v8::Array> v8array(value.As<v8::Array>()); if (visitedObjects.contains(v8array)) { // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty array (and no error is thrown). return result; } visitedObjects.insert(v8array); uint32_t length = v8array->Length(); for (uint32_t i = 0; i < length; ++i) { v8::Local<v8::Value> element = v8array->Get(i); if (!element->IsFunction()) result.append(toJsonValue(element, visitedObjects)); } visitedObjects.remove(v8array); return result; }
static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vector<v8::Handle<v8::Array> >& stack, v8::Isolate* isolate) { if (value->IsNumber() && !std::isnan(value->NumberValue())) return IDBKey::createNumber(value->NumberValue()); if (value->IsString()) return IDBKey::createString(toCoreString(value.As<v8::String>())); if (value->IsDate() && !std::isnan(value->NumberValue())) return IDBKey::createDate(value->NumberValue()); if (value->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); if (stack.contains(array)) return 0; if (stack.size() >= maximumDepth) return 0; stack.append(array); IDBKey::KeyArray subkeys; uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { v8::Local<v8::Value> item = array->Get(v8::Int32::New(i, isolate)); RefPtr<IDBKey> subkey = createIDBKeyFromValue(item, stack, isolate); if (!subkey) subkeys.append(IDBKey::createInvalid()); else subkeys.append(subkey); } stack.removeLast(); return IDBKey::createArray(subkeys); } return 0; }
static result_type from_v8(v8::Isolate* isolate, v8::Handle<v8::Value> value) { v8::HandleScope scope(isolate); result_type result; if (value->IsArray()) { v8::Local<v8::Array> arr = value.As<v8::Array>(); v8::Local<v8::Value> x = arr->Get(0), y = arr->Get(1); if (arr->Length() != 2 || !x->IsNumber() || !y->IsNumber()) { throw std::invalid_argument("expected [x, y] array"); } result.x = v8pp::from_v8<T>(isolate, x); result.y = v8pp::from_v8<T>(isolate, y); } else if (value->IsObject()) { v8::Local<v8::Object> obj = value.As<v8::Object>(); if (!get_option(isolate, obj, "x", result.x) || !get_option(isolate, obj, "y", result.y)) { throw std::invalid_argument("expected {x, y} object"); } } else { throw std::invalid_argument("expected [x, y] array or {x, y} object"); } return result; }
static result_type from_v8(v8::Isolate* isolate, v8::Handle<v8::Value> value) { v8::HandleScope scope(isolate); result_type result; if (value->IsArray()) { v8::Local<v8::Array> arr = value.As<v8::Array>(); v8::Local<v8::Value> width = arr->Get(0), height = arr->Get(1); if (arr->Length() != 2 || !width->IsNumber() || !height->IsNumber()) { throw std::invalid_argument("expected [width, height] array"); } result.width = v8pp::from_v8<T>(isolate, width); result.height = v8pp::from_v8<T>(isolate, height); } else if (value->IsObject()) { v8::Local<v8::Object> obj = value.As<v8::Object>(); if (!get_option(isolate, obj, "width", result.width) || !get_option(isolate, obj, "height", result.height)) { throw std::invalid_argument("expected {width, height} object"); } } else { throw std::invalid_argument("expected [width, height] array or {width, height} object"); } return result; }
static PassRefPtr<JSONValue> v8ToJSONValue(v8::Handle<v8::Value> value, int maxDepth, v8::Isolate* isolate) { if (value.IsEmpty()) { ASSERT_NOT_REACHED(); return 0; } if (!maxDepth) return 0; maxDepth--; if (value->IsNull() || value->IsUndefined()) return JSONValue::null(); if (value->IsBoolean()) return JSONBasicValue::create(value->BooleanValue()); if (value->IsNumber()) return JSONBasicValue::create(value->NumberValue()); if (value->IsString()) return JSONString::create(toCoreString(value.As<v8::String>())); if (value->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); RefPtr<JSONArray> inspectorArray = JSONArray::create(); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; i++) { v8::Local<v8::Value> value = array->Get(v8::Int32::New(isolate, i)); RefPtr<JSONValue> element = v8ToJSONValue(value, maxDepth, isolate); if (!element) return 0; inspectorArray->pushValue(element); } return inspectorArray; } if (value->IsObject()) { RefPtr<JSONObject> jsonObject = JSONObject::create(); v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); v8::Local<v8::Array> propertyNames = object->GetPropertyNames(); uint32_t length = propertyNames->Length(); for (uint32_t i = 0; i < length; i++) { v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(isolate, i)); // FIXME(yurys): v8::Object should support GetOwnPropertyNames if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name))) continue; RefPtr<JSONValue> propertyValue = v8ToJSONValue(object->Get(name), maxDepth, isolate); if (!propertyValue) return 0; V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, nameString, name, 0); jsonObject->setValue(nameString, propertyValue); } return jsonObject; } ASSERT_NOT_REACHED(); return 0; }
static PassRefPtr<InspectorValue> v8ToInspectorValue(v8::Handle<v8::Value> value, int maxDepth) { if (value.IsEmpty()) { ASSERT_NOT_REACHED(); return 0; } if (!maxDepth) return 0; maxDepth--; if (value->IsNull() || value->IsUndefined()) return InspectorValue::null(); if (value->IsBoolean()) return InspectorBasicValue::create(value->BooleanValue()); if (value->IsNumber()) return InspectorBasicValue::create(value->NumberValue()); if (value->IsString()) return InspectorString::create(toWebCoreString(value)); if (value->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); RefPtr<InspectorArray> inspectorArray = InspectorArray::create(); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; i++) { v8::Local<v8::Value> value = array->Get(v8::Int32::New(i)); RefPtr<InspectorValue> element = v8ToInspectorValue(value, maxDepth); if (!element) return 0; inspectorArray->pushValue(element); } return inspectorArray; } if (value->IsObject()) { RefPtr<InspectorObject> inspectorObject = InspectorObject::create(); v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); v8::Local<v8::Array> propertyNames = object->GetPropertyNames(); uint32_t length = propertyNames->Length(); for (uint32_t i = 0; i < length; i++) { v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(i)); // FIXME(yurys): v8::Object should support GetOwnPropertyNames if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name))) continue; RefPtr<InspectorValue> propertyValue = v8ToInspectorValue(object->Get(name), maxDepth); if (!propertyValue) return 0; inspectorObject->setValue(toWebCoreStringWithNullCheck(name), propertyValue); } return inspectorObject; } ASSERT_NOT_REACHED(); return 0; }
// Returns number of bytes written. ssize_t DecodeWrite(char *buf, size_t buflen, v8::Handle<v8::Value> val, enum encoding encoding) { v8::HandleScope scope; // XXX // A lot of improvement can be made here. See: // http://code.google.com/p/v8/issues/detail?id=270 // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611 if (val->IsArray()) { fprintf(stderr, "'raw' encoding (array of integers) has been removed. " "Use 'binary'.\n"); assert(0); return -1; } v8::Local<v8::String> str = val->ToString(); if (encoding == UTF8) { str->WriteUtf8(buf, buflen); return buflen; } if (encoding == ASCII) { str->WriteAscii(buf, 0, buflen); return buflen; } // THIS IS AWFUL!!! FIXME assert(encoding == BINARY); uint16_t * twobytebuf = new uint16_t[buflen]; str->Write(twobytebuf, 0, buflen); for (size_t i = 0; i < buflen; i++) { unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]); assert(b[1] == 0); buf[i] = b[0]; } delete [] twobytebuf; return buflen; }
// Returns -1 if the handle was not valid for decoding ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) { v8::HandleScope scope; if (val->IsArray()) { fprintf(stderr, "'raw' encoding (array of integers) has been removed. " "Use 'binary'.\n"); assert(0); return -1; } v8::Local<v8::String> str = val->ToString(); if (encoding == UTF8) return str->Utf8Length(); return str->Length(); }
Object^ V8Interop::FromV8(v8::Handle<v8::Value> value) { if (value->IsString()) { return FromV8String(value); } else if (value->IsBoolean()) { return FromV8Boolean(value); } else if (value->IsInt32()) { return FromV8Int32(value); } else if (value->IsArray()) { return FromV8Array(value); } else if (value->IsDate()) { return FromV8Date(value); } else if (value->IsNumber()) { return FromV8Double(value); } else if (value->IsFunction()) { return FromV8Function(value); } else if (value->IsExternal()) { return FromV8External(value); } else if (value->IsObject()) { return FromV8Object(value); } else if (value->IsUndefined() || value->IsNull()) { return nullptr; } return nullptr; }
QJsonValue QV8JsonWrapper::toJsonValue(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects) { if (value->IsString()) return QJsonValue(QJSConverter::toString(value.As<v8::String>())); else if (value->IsNumber()) return QJsonValue(value->NumberValue()); else if (value->IsBoolean()) return QJsonValue(value->BooleanValue()); else if (value->IsArray()) return toJsonArray(value.As<v8::Array>(), visitedObjects); else if (value->IsObject()) return toJsonObject(value.As<v8::Object>(), visitedObjects); else if (value->IsNull()) return QJsonValue(QJsonValue::Null); else return QJsonValue(QJsonValue::Undefined); }
bool CJavaFunction::CanConvert(jclass clazz, v8::Handle<v8::Value> value) { jni::V8Env env(m_pEnv); if (value->IsTrue() || value->IsFalse() || value->IsBoolean()) { return env.IsAssignableFrom(env.buildins.java.lang.Boolean, clazz); } else if (value->IsInt32() || value->IsUint32()) { return env.IsAssignableFrom(env.buildins.java.lang.Long, clazz) || env.IsAssignableFrom(env.buildins.java.lang.Integer, clazz) || env.IsAssignableFrom(env.buildins.java.lang.Short, clazz) || env.IsAssignableFrom(env.buildins.java.lang.Byte, clazz); } else if (value->IsNumber()) { return env.IsAssignableFrom(env.buildins.java.lang.Double, clazz) || env.IsAssignableFrom(env.buildins.java.lang.Float, clazz); } else if (value->IsString()) { return env.IsAssignableFrom(env.buildins.java.lang.String, clazz); } else if (value->IsDate()) { return env.IsAssignableFrom(env.buildins.java.util.Date, clazz); } else if (value->IsArray()) { return env.IsAssignableFrom(env.buildins.lu.flier.script.V8Array, clazz); } else if (value.IsEmpty() || value->IsNull() || value->IsUndefined() || value->IsObject()) { return true; } return false; }
static Value v8ValueToValue(v8::Handle<v8::Value> v8Value) { v8::HandleScope scope; if (v8Value->IsArray()) { List<Value> value; const v8::Handle<v8::Array> v8Array = v8::Handle<v8::Array>::Cast(v8Value); const uint32_t size = v8Array->Length(); for (uint32_t i = 0; i < size; ++i) { if (v8Array->Has(i)) value.append(v8ValueToValue(v8Array->Get(i))); else value.append(Value()); } return Value(value); } else if (v8Value->IsObject()) { Map<String, Value> value; const v8::Handle<v8::Object> v8Object = v8Value->ToObject(); const v8::Handle<v8::Array> props = v8Object->GetPropertyNames(); const uint32_t size = props->Length(); for (uint32_t i = 0; i < size; ++i) { assert(props->Has(i)); const v8::Handle<v8::Value> name = props->Get(i); value[String(*v8::String::Utf8Value(name))] = v8ValueToValue(v8Object->Get(name)); } return Value(value); } else if (v8Value->IsBoolean()) { return Value(v8Value->BooleanValue()); } else if (v8Value->IsInt32() || v8Value->IsUint32()) { return Value(v8Value->Int32Value()); } else if (v8Value->IsNumber()) { return Value(v8Value->NumberValue()); } else if (v8Value->IsString()) { return Value(String(*v8::String::Utf8Value(v8Value))); } else { error() << "Unexpected v8 value type in JSONParser"; } // undefined or null? return Value(); }
void v8ToMongoElement( BSONObjBuilder & b , v8::Handle<v8::String> name , const string sname , v8::Handle<v8::Value> value ){ if ( value->IsString() ){ if ( sname == "$where" ) b.appendCode( sname.c_str() , toSTLString( value ).c_str() ); else b.append( sname.c_str() , toSTLString( value ).c_str() ); return; } if ( value->IsFunction() ){ b.appendCode( sname.c_str() , toSTLString( value ).c_str() ); return; } if ( value->IsNumber() ){ b.append( sname.c_str() , value->ToNumber()->Value() ); return; } if ( value->IsArray() ){ BSONObj sub = v8ToMongo( value->ToObject() ); b.appendArray( sname.c_str() , sub ); return; } if ( value->IsDate() ){ b.appendDate( sname.c_str() , (unsigned long long )(v8::Date::Cast( *value )->NumberValue()) ); return; } if ( value->IsObject() ){ string s = toSTLString( value ); if ( s.size() && s[0] == '/' ){ s = s.substr( 1 ); string r = s.substr( 0 , s.find( "/" ) ); string o = s.substr( s.find( "/" ) + 1 ); b.appendRegex( sname.c_str() , r.c_str() , o.c_str() ); } else if ( value->ToObject()->GetPrototype()->IsObject() && value->ToObject()->GetPrototype()->ToObject()->HasRealNamedProperty( String::New( "isObjectId" ) ) ){ OID oid; oid.init( toSTLString( value ) ); b.appendOID( sname.c_str() , &oid ); } else { BSONObj sub = v8ToMongo( value->ToObject() ); b.append( sname.c_str() , sub ); } return; } if ( value->IsBoolean() ){ b.appendBool( sname.c_str() , value->ToBoolean()->Value() ); return; } else if ( value->IsUndefined() ){ return; } else if ( value->IsNull() ){ b.appendNull( sname.c_str() ); return; } cout << "don't know how to covert to mongo field [" << name << "]\t" << value << endl; }
bool IsMatrix(v8::Handle<v8::Value> v) { return (!v.IsEmpty() && v->IsArray() && Handle<Array>::Cast(v)->Length() >= 16); }
static int FillShapeValueJson (v8::Isolate* isolate, VocShaper* shaper, TRI_shape_value_t* dst, v8::Handle<v8::Value> const json, size_t level, set<int>& seenHashes, vector<v8::Handle<v8::Object>>& seenObjects, bool create) { v8::HandleScope scope(isolate); if (json->IsRegExp() || json->IsFunction() || json->IsExternal()) { LOG_TRACE("shaper failed because regexp/function/external/date object cannot be converted"); return TRI_ERROR_BAD_PARAMETER; } if (json->IsNull() || json->IsUndefined()) { return FillShapeValueNull(shaper, dst); } if (json->IsBoolean()) { return FillShapeValueBoolean(shaper, dst, json->ToBoolean()); } if (json->IsBooleanObject()) { return FillShapeValueBoolean(shaper, dst, v8::Handle<v8::BooleanObject>::Cast(json)); } if (json->IsNumber()) { return FillShapeValueNumber(shaper, dst, json->ToNumber()); } if (json->IsNumberObject()) { return FillShapeValueNumber(shaper, dst, v8::Handle<v8::NumberObject>::Cast(json)); } if (json->IsString()) { return FillShapeValueString(shaper, dst, json->ToString()); } if (json->IsStringObject()) { return FillShapeValueString(shaper, dst, v8::Handle<v8::StringObject>::Cast(json)->ValueOf()); } else if (json->IsArray()) { return FillShapeValueList(isolate, shaper, dst, v8::Handle<v8::Array>::Cast(json), level, seenHashes, seenObjects, create); } if (json->IsObject()) { v8::Handle<v8::Object> o = json->ToObject(); v8::Handle<v8::String> toJsonString = TRI_V8_PAIR_STRING("toJSON", 6); if (o->Has(toJsonString)) { v8::Handle<v8::Value> func = o->Get(toJsonString); if (func->IsFunction()) { v8::Handle<v8::Function> toJson = v8::Handle<v8::Function>::Cast(func); v8::Handle<v8::Value> args; v8::Handle<v8::Value> result = toJson->Call(o, 0, &args); if (! result.IsEmpty()) { return FillShapeValueString(shaper, dst, result->ToString()); } } } // fall-through intentional // check for cycles int hash = o->GetIdentityHash(); if (seenHashes.find(hash) != seenHashes.end()) { for (auto it = seenObjects.begin(); it != seenObjects.end(); ++it) { if (json->StrictEquals(*it)) { return TRI_ERROR_ARANGO_SHAPER_FAILED; } } } else { seenHashes.insert(hash); } seenObjects.push_back(o); int res = FillShapeValueArray(isolate, shaper, dst, json->ToObject(), level, seenHashes, seenObjects, create); seenObjects.pop_back(); // cannot remove hash value from seenHashes because multiple objects might have the same // hash values (collisions) return res; } LOG_TRACE("shaper failed to convert object"); return TRI_ERROR_BAD_PARAMETER; }
void QV8Worker::serialize(QByteArray &data, v8::Handle<v8::Value> v, QV8Engine *engine) { if (v.IsEmpty()) { } else if (v->IsUndefined()) { push(data, valueheader(WorkerUndefined)); } else if (v->IsNull()) { push(data, valueheader(WorkerNull)); } else if (v->IsTrue()) { push(data, valueheader(WorkerTrue)); } else if (v->IsFalse()) { push(data, valueheader(WorkerFalse)); } else if (v->IsString()) { v8::Handle<v8::String> string = v->ToString(); int length = string->Length() + 1; if (length > 0xFFFFFF) { push(data, valueheader(WorkerUndefined)); return; } int utf16size = ALIGN(length * sizeof(uint16_t)); reserve(data, utf16size + sizeof(quint32)); push(data, valueheader(WorkerString, length)); int offset = data.size(); data.resize(data.size() + utf16size); char *buffer = data.data() + offset; string->Write((uint16_t*)buffer); } else if (v->IsFunction()) { // XXX TODO: Implement passing function objects between the main and // worker scripts push(data, valueheader(WorkerUndefined)); } else if (v->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(v); uint32_t length = array->Length(); if (length > 0xFFFFFF) { push(data, valueheader(WorkerUndefined)); return; } reserve(data, sizeof(quint32) + length * sizeof(quint32)); push(data, valueheader(WorkerArray, length)); for (uint32_t ii = 0; ii < length; ++ii) serialize(data, array->Get(ii), engine); } else if (v->IsInt32()) { reserve(data, 2 * sizeof(quint32)); push(data, valueheader(WorkerInt32)); push(data, (quint32)v->Int32Value()); } else if (v->IsUint32()) { reserve(data, 2 * sizeof(quint32)); push(data, valueheader(WorkerUint32)); push(data, v->Uint32Value()); } else if (v->IsNumber()) { reserve(data, sizeof(quint32) + sizeof(double)); push(data, valueheader(WorkerNumber)); push(data, v->NumberValue()); } else if (v->IsDate()) { reserve(data, sizeof(quint32) + sizeof(double)); push(data, valueheader(WorkerDate)); push(data, v8::Handle<v8::Date>::Cast(v)->NumberValue()); } else if (v->IsRegExp()) { v8::Handle<v8::RegExp> regexp = v8::Handle<v8::RegExp>::Cast(v); quint32 flags = regexp->GetFlags(); v8::Local<v8::String> source = regexp->GetSource(); int length = source->Length() + 1; if (length > 0xFFFFFF) { push(data, valueheader(WorkerUndefined)); return; } int utf16size = ALIGN(length * sizeof(uint16_t)); reserve(data, sizeof(quint32) + utf16size); push(data, valueheader(WorkerRegexp, flags)); push(data, (quint32)length); int offset = data.size(); data.resize(data.size() + utf16size); char *buffer = data.data() + offset; source->Write((uint16_t*)buffer); } else if (v->IsObject() && !v->ToObject()->GetExternalResource()) { v8::Handle<v8::Object> object = v->ToObject(); v8::Local<v8::Array> properties = engine->getOwnPropertyNames(object); quint32 length = properties->Length(); if (length > 0xFFFFFF) { push(data, valueheader(WorkerUndefined)); return; } push(data, valueheader(WorkerObject, length)); v8::TryCatch tc; for (quint32 ii = 0; ii < length; ++ii) { v8::Local<v8::String> str = properties->Get(ii)->ToString(); serialize(data, str, engine); v8::Local<v8::Value> val = object->Get(str); if (tc.HasCaught()) { serialize(data, v8::Undefined(), engine); tc.Reset(); } else { serialize(data, val, engine); } } } else if (engine->isQObject(v)) { // XXX TODO: Generalize passing objects between the main thread and worker scripts so // that others can trivially plug in their elements. QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(engine->toQObject(v)); if (lm && lm->agent()) { QDeclarativeListModelWorkerAgent *agent = lm->agent(); agent->addref(); push(data, valueheader(WorkerListModel)); push(data, (void *)agent); return; } // No other QObject's are allowed to be sent push(data, valueheader(WorkerUndefined)); } else { push(data, valueheader(WorkerUndefined)); } }
static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, v8::Handle<v8::Value> json, set<int>& seenHashes, vector< v8::Handle<v8::Object> >& seenObjects) { if (json->IsObject()) { v8::Handle<v8::Object> o = json->ToObject(); int hash = o->GetIdentityHash(); if (seenHashes.find(hash) != seenHashes.end()) { LOG_TRACE("found hash %d", hash); for (vector< v8::Handle<v8::Object> >::iterator i = seenObjects.begin(); i != seenObjects.end(); ++i) { if (json->StrictEquals(*i)) { LOG_TRACE("found duplicate for hash %d", hash); return FillShapeValueNull(shaper, dst); } } seenObjects.push_back(o); } else { seenHashes.insert(hash); seenObjects.push_back(o); } } if (json->IsNull()) { return FillShapeValueNull(shaper, dst); } if (json->IsBoolean()) { return FillShapeValueBoolean(shaper, dst, json->ToBoolean()); } if (json->IsBooleanObject()) { v8::Handle<v8::BooleanObject> bo = v8::Handle<v8::BooleanObject>::Cast(json); return FillShapeValueBoolean(shaper, dst, bo); } if (json->IsNumber()) { return FillShapeValueNumber(shaper, dst, json->ToNumber()); } if (json->IsNumberObject()) { v8::Handle<v8::NumberObject> no = v8::Handle<v8::NumberObject>::Cast(json); return FillShapeValueNumber(shaper, dst, no); } if (json->IsString()) { return FillShapeValueString(shaper, dst, json->ToString()); } if (json->IsStringObject()) { v8::Handle<v8::StringObject> so = v8::Handle<v8::StringObject>::Cast(json); return FillShapeValueString(shaper, dst, so->StringValue()); } if (json->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(json); return FillShapeValueList(shaper, dst, array, seenHashes, seenObjects); } if (json->IsObject()) { return FillShapeValueArray(shaper, dst, json->ToObject(), seenHashes, seenObjects); } return false; }
static int V8ToVPack(BuilderContext& context, v8::Handle<v8::Value> const parameter, std::string const& attributeName, bool inObject) { if (parameter->IsNull() || parameter->IsUndefined()) { AddValue(context, attributeName, inObject, VPackValue(VPackValueType::Null)); return TRI_ERROR_NO_ERROR; } if (parameter->IsBoolean()) { AddValue(context, attributeName, inObject, VPackValue(parameter->ToBoolean()->Value())); return TRI_ERROR_NO_ERROR; } if (parameter->IsNumber()) { if (parameter->IsInt32()) { AddValue(context, attributeName, inObject, VPackValue(parameter->ToInt32()->Value())); return TRI_ERROR_NO_ERROR; } if (parameter->IsUint32()) { AddValue(context, attributeName, inObject, VPackValue(parameter->ToUint32()->Value())); return TRI_ERROR_NO_ERROR; } AddValue(context, attributeName, inObject, VPackValue(parameter->ToNumber()->Value())); return TRI_ERROR_NO_ERROR; } if (parameter->IsString()) { v8::String::Utf8Value str(parameter->ToString()); if (*str == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } AddValuePair(context, attributeName, inObject, VPackValuePair(*str, str.length(), VPackValueType::String)); return TRI_ERROR_NO_ERROR; } if (parameter->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(parameter); AddValue(context, attributeName, inObject, VPackValue(VPackValueType::Array)); uint32_t const n = array->Length(); for (uint32_t i = 0; i < n; ++i) { v8::Handle<v8::Value> value = array->Get(i); if (value->IsUndefined()) { // ignore array values which are undefined continue; } if (++context.level > MaxLevels) { // too much recursion return TRI_ERROR_BAD_PARAMETER; } int res = V8ToVPack<performAllChecks>(context, value, NoAttribute, false); --context.level; if (res != TRI_ERROR_NO_ERROR) { return res; } } if (!context.keepTopLevelOpen || context.level > 0) { context.builder.close(); } return TRI_ERROR_NO_ERROR; } if (parameter->IsObject()) { if (performAllChecks) { if (parameter->IsBooleanObject()) { AddValue(context, attributeName, inObject, VPackValue(v8::Handle<v8::BooleanObject>::Cast(parameter) ->BooleanValue())); return TRI_ERROR_NO_ERROR; } if (parameter->IsNumberObject()) { AddValue(context, attributeName, inObject, VPackValue(v8::Handle<v8::NumberObject>::Cast(parameter) ->NumberValue())); return TRI_ERROR_NO_ERROR; } if (parameter->IsStringObject()) { v8::String::Utf8Value str(parameter->ToString()); if (*str == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } AddValuePair(context, attributeName, inObject, VPackValuePair(*str, str.length(), VPackValueType::String)); return TRI_ERROR_NO_ERROR; } if (parameter->IsRegExp() || parameter->IsFunction() || parameter->IsExternal()) { return TRI_ERROR_BAD_PARAMETER; } } v8::Handle<v8::Object> o = parameter->ToObject(); if (performAllChecks) { // first check if the object has a "toJSON" function if (o->Has(context.toJsonKey)) { // call it if yes v8::Handle<v8::Value> func = o->Get(context.toJsonKey); if (func->IsFunction()) { v8::Handle<v8::Function> toJson = v8::Handle<v8::Function>::Cast(func); v8::Handle<v8::Value> args; v8::Handle<v8::Value> converted = toJson->Call(o, 0, &args); if (!converted.IsEmpty()) { // return whatever toJSON returned v8::String::Utf8Value str(converted->ToString()); if (*str == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } // this passes ownership for the utf8 string to the JSON object AddValuePair(context, attributeName, inObject, VPackValuePair(*str, str.length(), VPackValueType::String)); return TRI_ERROR_NO_ERROR; } } // fall-through intentional } } v8::Handle<v8::Array> names = o->GetOwnPropertyNames(); uint32_t const n = names->Length(); AddValue(context, attributeName, inObject, VPackValue(VPackValueType::Object)); for (uint32_t i = 0; i < n; ++i) { // process attribute name v8::Handle<v8::Value> key = names->Get(i); v8::String::Utf8Value str(key); if (*str == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } v8::Handle<v8::Value> value = o->Get(key); if (value->IsUndefined()) { // ignore object values which are undefined continue; } if (++context.level > MaxLevels) { // too much recursion return TRI_ERROR_BAD_PARAMETER; } int res = V8ToVPack<performAllChecks>(context, value, *str, true); --context.level; if (res != TRI_ERROR_NO_ERROR) { return res; } } if (!context.keepTopLevelOpen || context.level > 0) { context.builder.close(); } return TRI_ERROR_NO_ERROR; } return TRI_ERROR_BAD_PARAMETER; }
void v8ToMongoElement( BSONObjBuilder & b , v8::Handle<v8::String> name , const string sname , v8::Handle<v8::Value> value ){ if ( value->IsString() ){ b.append( sname.c_str() , toSTLString( value ).c_str() ); return; } if ( value->IsFunction() ){ b.appendCode( sname.c_str() , toSTLString( value ).c_str() ); return; } if ( value->IsNumber() ){ if ( value->IsInt32() ) b.append( sname.c_str(), int( value->ToInt32()->Value() ) ); else b.append( sname.c_str() , value->ToNumber()->Value() ); return; } if ( value->IsArray() ){ BSONObj sub = v8ToMongo( value->ToObject() ); b.appendArray( sname.c_str() , sub ); return; } if ( value->IsDate() ){ b.appendDate( sname.c_str() , Date_t(v8::Date::Cast( *value )->NumberValue()) ); return; } if ( value->IsExternal() ) return; if ( value->IsObject() ){ // The user could potentially modify the fields of these special objects, // wreaking havoc when we attempt to reinterpret them. Not doing any validation // for now... Local< v8::Object > obj = value->ToObject(); if ( obj->InternalFieldCount() && obj->GetInternalField( 0 )->IsNumber() ) { switch( obj->GetInternalField( 0 )->ToInt32()->Value() ) { // NOTE Uint32's Value() gave me a linking error, so going with this instead case Timestamp: b.appendTimestamp( sname.c_str(), Date_t( v8::Date::Cast( *obj->Get( v8::String::New( "time" ) ) )->NumberValue() ), obj->Get( v8::String::New( "i" ) )->ToInt32()->Value() ); return; case MinKey: b.appendMinKey( sname.c_str() ); return; case MaxKey: b.appendMaxKey( sname.c_str() ); return; default: assert( "invalid internal field" == 0 ); } } string s = toSTLString( value ); if ( s.size() && s[0] == '/' ){ s = s.substr( 1 ); string r = s.substr( 0 , s.rfind( "/" ) ); string o = s.substr( s.rfind( "/" ) + 1 ); b.appendRegex( sname.c_str() , r.c_str() , o.c_str() ); } else if ( value->ToObject()->GetPrototype()->IsObject() && value->ToObject()->GetPrototype()->ToObject()->HasRealNamedProperty( v8::String::New( "isObjectId" ) ) ){ OID oid; oid.init( toSTLString( value ) ); b.appendOID( sname.c_str() , &oid ); } else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__NumberLong" ) ).IsEmpty() ) { // TODO might be nice to potentially speed this up with an indexed internal // field, but I don't yet know how to use an ObjectTemplate with a // constructor. unsigned long long val = ( (unsigned long long)( value->ToObject()->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) + (unsigned)( value->ToObject()->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() ); b.append( sname.c_str(), (long long)val ); } else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__DBPointer" ) ).IsEmpty() ) { OID oid; oid.init( toSTLString( value->ToObject()->Get( v8::String::New( "id" ) ) ) ); string ns = toSTLString( value->ToObject()->Get( v8::String::New( "ns" ) ) ); b.appendDBRef( sname.c_str(), ns.c_str(), oid ); } else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__BinData" ) ).IsEmpty() ) { int len = obj->Get( v8::String::New( "len" ) )->ToInt32()->Value(); v8::String::Utf8Value data( obj->Get( v8::String::New( "data" ) ) ); const char *dataArray = *data; assert( data.length() == len ); b.appendBinData( sname.c_str(), len, mongo::BinDataType( obj->Get( v8::String::New( "type" ) )->ToInt32()->Value() ), dataArray ); } else { BSONObj sub = v8ToMongo( value->ToObject() ); b.append( sname.c_str() , sub ); } return; } if ( value->IsBoolean() ){ b.appendBool( sname.c_str() , value->ToBoolean()->Value() ); return; } else if ( value->IsUndefined() ){ b.appendUndefined( sname.c_str() ); return; } else if ( value->IsNull() ){ b.appendNull( sname.c_str() ); return; } cout << "don't know how to convert to mongo field [" << name << "]\t" << value << endl; }