result_t util_base::last(v8::Local<v8::Value> v, v8::Local<v8::Value> &retVal) { Isolate* isolate = Isolate::current(); if (v->IsUndefined() || v->IsNull()) { retVal = v8::Undefined(isolate->m_isolate); return 0; } if (!v->IsArray()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(v); int32_t len = arr->Length(); if (len == 0) { retVal = v8::Undefined(isolate->m_isolate); return 0; } retVal = arr->Get(len - 1); return 0; }
void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), info.GetIsolate()); if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } // Opener can be shadowed if it is in the same domain. // Have a special handling of null value to behave // like Firefox. See bug http://b/1224887 & http://b/791706. if (value->IsNull()) { // impl->frame() cannot be null, // otherwise, SameOrigin check would have failed. ASSERT(impl->frame()); impl->frame()->loader().setOpener(0); } // Delete the accessor from this object. info.Holder()->Delete(v8AtomicString(info.GetIsolate(), "opener")); // Put property on the front (this) object. if (info.This()->IsObject()) v8::Handle<v8::Object>::Cast(info.This())->Set(v8AtomicString(info.GetIsolate(), "opener"), value); }
Dictionary::Dictionary(v8::Isolate* isolate, v8::Local<v8::Value> dictionaryObject, ExceptionState& exceptionState) : m_isolate(isolate) { DCHECK(isolate); // https://heycam.github.io/webidl/#es-dictionary // Type of an ECMAScript value must be Undefined, Null or Object. if (dictionaryObject.IsEmpty() || dictionaryObject->IsUndefined()) { m_valueType = ValueType::Undefined; return; } if (dictionaryObject->IsNull()) { m_valueType = ValueType::Null; return; } if (dictionaryObject->IsObject()) { m_valueType = ValueType::Object; m_dictionaryObject = dictionaryObject.As<v8::Object>(); return; } exceptionState.throwTypeError( "The dictionary provided is neither undefined, null nor an Object."); }
void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result) { VOID_TO_NPVARIANT(*result); // It is really the caller's responsibility to deal with the empty handle case because there could be different actions to // take in different contexts. ASSERT(!object.IsEmpty()); if (object.IsEmpty()) return; if (object->IsInt32()) INT32_TO_NPVARIANT(object->NumberValue(), *result); else if (object->IsNumber()) DOUBLE_TO_NPVARIANT(object->NumberValue(), *result); else if (object->IsBoolean()) BOOLEAN_TO_NPVARIANT(object->BooleanValue(), *result); else if (object->IsNull()) NULL_TO_NPVARIANT(*result); else if (object->IsUndefined()) VOID_TO_NPVARIANT(*result); else if (object->IsString()) { v8::String::Utf8Value utf8(object); char* utf8_chars = strdup(*utf8); STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result); } else if (object->IsObject()) { WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext()); NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window); if (npobject) _NPN_RegisterObject(npobject, owner); OBJECT_TO_NPVARIANT(npobject, *result); } }
result_t util_base::isEmpty(v8::Local<v8::Value> v, bool& retVal) { if (v->IsNull()) { retVal = true; return 0; } if (v->IsString()) { retVal = v8::Local<v8::String>::Cast(v)->Length() == 0; return 0; } if (v->IsStringObject()) { retVal = v8::Local<v8::StringObject>::Cast(v)->ValueOf()->Length() == 0; return 0; } if (v->IsArray()) { retVal = v8::Local<v8::Array>::Cast(v)->Length() == 0; return 0; } if (v->IsObject()) { retVal = v->ToObject()->GetOwnPropertyNames()->Length() == 0; return 0; } retVal = true; return 0; }
result_t util_base::last(v8::Local<v8::Value> v, int32_t n, v8::Local<v8::Value> &retVal) { Isolate* isolate = Isolate::current(); if (v->IsUndefined() || v->IsNull() || n <= 0) { retVal = v8::Array::New(isolate->m_isolate); return 0; } if (!v->IsArray()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(v); int32_t len = arr->Length(); int32_t i; if (n > len) n = len; v8::Local<v8::Array> arr1 = v8::Array::New(isolate->m_isolate); for (i = 0; i < n; i ++) arr1->Set(i, arr->Get(len - n + i)); retVal = arr1; return 0; }
void V8Window::openerAttributeSetterCustom( v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { v8::Isolate* isolate = info.GetIsolate(); DOMWindow* impl = V8Window::toImpl(info.Holder()); ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), isolate); if (!BindingSecurity::shouldAllowAccessTo(currentDOMWindow(info.GetIsolate()), impl, exceptionState)) { return; } // Opener can be shadowed if it is in the same domain. // Have a special handling of null value to behave // like Firefox. See bug http://b/1224887 & http://b/791706. if (value->IsNull()) { // impl->frame() has to be a non-null LocalFrame. Otherwise, the // same-origin check would have failed. ASSERT(impl->frame()); toLocalFrame(impl->frame())->loader().setOpener(0); } // Delete the accessor from the inner object. info.Holder()->Delete(isolate->GetCurrentContext(), v8AtomicString(isolate, "opener")); // Put property on the inner object. if (info.Holder()->IsObject()) { v8::Maybe<bool> unused = v8::Local<v8::Object>::Cast(info.Holder()) ->Set(isolate->GetCurrentContext(), v8AtomicString(isolate, "opener"), value); ALLOW_UNUSED_LOCAL(unused); } }
jobject TypeConverter::jsValueToJavaError(JNIEnv *env, v8::Local<v8::Value> jsValue, bool* isNew) { if (jsValue->IsObject()) { v8::Handle<v8::Object> jsObject = jsValue->ToObject(); // If it's a java object, we just return null for now. if (!JavaObject::isJavaObject(jsObject)) { Handle<String> stackString = String::New("stack"), messageString = String::New("message"); if (jsObject->HasOwnProperty(stackString) || jsObject->HasOwnProperty(messageString)) { bool keyIsNew, valueIsNew; *isNew = true; v8::Local<v8::Value> jsObjectMessageProperty = jsObject->GetRealNamedProperty(messageString); v8::Local<v8::Value> jsObjectStackProperty = jsObject->GetRealNamedProperty(stackString); return env->NewObject(JNIUtil::krollExceptionClass, JNIUtil::krollExceptionInitMethod, TypeConverter::jsValueToJavaString(env, jsObjectMessageProperty), TypeConverter::jsValueToJavaString(env, jsObjectStackProperty)); } } } else { *isNew = true; return env->NewObject(JNIUtil::krollExceptionClass, JNIUtil::krollExceptionInitMethod, TypeConverter::jsValueToJavaString(env, jsValue), NULL); } if (!jsValue->IsNull() && !jsValue->IsUndefined()) { LOGW(TAG, "jsValueToJavaObject returning null."); } return NULL; }
void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result) { VOID_TO_NPVARIANT(*result); // It is really the caller's responsibility to deal with the empty handle case because there could be different actions to // take in different contexts. ASSERT(!object.IsEmpty()); if (object.IsEmpty()) return; if (object->IsNumber()) DOUBLE_TO_NPVARIANT(object->NumberValue(), *result); else if (object->IsBoolean()) BOOLEAN_TO_NPVARIANT(object->BooleanValue(), *result); else if (object->IsNull()) NULL_TO_NPVARIANT(*result); else if (object->IsUndefined()) VOID_TO_NPVARIANT(*result); else if (object->IsString()) { v8::Handle<v8::String> str = object->ToString(); int length = str->Utf8Length() + 1; char* utf8Chars = reinterpret_cast<char*>(malloc(length)); str->WriteUtf8(utf8Chars, length, 0, v8::String::HINT_MANY_WRITES_EXPECTED); STRINGN_TO_NPVARIANT(utf8Chars, length-1, *result); } else if (object->IsObject()) { DOMWindow* window = V8Proxy::retrieveWindow(V8Proxy::currentContext()); NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window); if (npobject) _NPN_RegisterObject(npobject, owner); OBJECT_TO_NPVARIANT(npobject, *result); } }
String16 toProtocolString(v8::Local<v8::String> value) { if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) return String16(); std::unique_ptr<UChar[]> buffer(new UChar[value->Length()]); value->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0, value->Length()); return String16(buffer.get(), value->Length()); }
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) { if(arg->IsNull() || arg->IsUndefined()) { return NULL; } if(arg->IsArray()) { v8::Local<v8::Array> array = v8::Array::Cast(*arg); uint32_t arraySize = array->Length(); jclass objectClazz = env->FindClass("java/lang/Object"); jobjectArray result = env->NewObjectArray(arraySize, objectClazz, NULL); for(uint32_t i=0; i<arraySize; i++) { jobject val = v8ToJava(env, array->Get(i)); env->SetObjectArrayElement(result, i, val); } return result; } if(arg->IsString()) { v8::String::AsciiValue val(arg->ToString()); return env->NewStringUTF(*val); } if(arg->IsInt32() || arg->IsUint32()) { jint val = arg->ToInt32()->Value(); jclass clazz = env->FindClass("java/lang/Integer"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(I)V"); return env->NewObject(clazz, constructor, val); } if(arg->IsNumber()) { jdouble val = arg->ToNumber()->Value(); jclass clazz = env->FindClass("java/lang/Double"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(D)V"); return env->NewObject(clazz, constructor, val); } if(arg->IsBoolean()) { jboolean val = arg->ToBoolean()->Value(); jclass clazz = env->FindClass("java/lang/Boolean"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V"); return env->NewObject(clazz, constructor, val); } if(arg->IsObject()) { v8::Local<v8::Object> obj = v8::Object::Cast(*arg); v8::String::AsciiValue constructorName(obj->GetConstructorName()); if(strcmp(*constructorName, "JavaObject") == 0) { JavaObject* javaObject = node::ObjectWrap::Unwrap<JavaObject>(obj); return javaObject->getObject(); } } // TODO: handle other arg types v8::String::AsciiValue typeStr(arg); printf("Unhandled type: %s\n", *typeStr); return NULL; }
result_t util_base::has(v8::Local<v8::Value> v, const char *key, bool &retVal) { if (v->IsUndefined() || v->IsNull()) { retVal = false; return 0; } if (!v->IsObject()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Object> obj = v->ToObject(); retVal = obj->HasOwnProperty(Isolate::current()->NewFromUtf8(key)); return 0; }
result_t util_base::unique(v8::Local<v8::Value> v, bool sorted, v8::Local<v8::Array> &retVal) { Isolate* isolate = Isolate::current(); if (v->IsUndefined() || v->IsNull()) { retVal = v8::Array::New(isolate->m_isolate); return 0; } if (!v->IsArray()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Array> arr1 = v8::Array::New(isolate->m_isolate); v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(v); int32_t len = arr->Length(); QuickArray<v8::Local<v8::Value> > vals; int32_t i, j, n = 0; vals.resize(len); for (i = 0; i < len; i ++) { v8::Local<v8::Value> val = arr->Get(i); for (j = i - 1; j >= 0; j --) if (!vals[j].IsEmpty()) { if (val->StrictEquals(vals[j])) break; if (sorted) { j = -1; break; } } if (j < 0) vals[i] = val; } for (i = 0; i < len; i ++) if (!vals[i].IsEmpty()) arr1->Set(n++, vals[i]); retVal = arr1; return 0; }
v8::Local<v8::Object> Convert::getJsObjectOrNull(v8::Local<v8::Value> js) { if (js->IsNull()) { Nan::EscapableHandleScope scope; v8::Local<v8::Object> newobj = Nan::New<v8::Object>(); Utility::Set(newobj, "special_hack_null_object", true); return scope.Escape(newobj); } else if (js->IsObject()) { return Convert::getJsObject(js); } throw std::runtime_error("object or null"); }
void transferHiddenDependency(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex) { if (oldValue) { V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue); if (oldListener) { v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject(); if (!oldListenerObject.IsEmpty()) removeHiddenDependency(object, oldListenerObject, cacheIndex); } } if (!newValue->IsNull() && !newValue->IsUndefined()) createHiddenDependency(object, newValue, cacheIndex); }
result_t util_base::pick(v8::Local<v8::Value> v, const v8::FunctionCallbackInfo<v8::Value> &args, v8::Local<v8::Object> &retVal) { Isolate* isolate = Isolate::current(); if (v->IsUndefined() || v->IsNull()) { retVal = v8::Object::New(isolate->m_isolate); return 0; } if (!v->IsObject()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Object> obj = v->ToObject(); v8::Local<v8::Object> obj1 = v8::Object::New(isolate->m_isolate); int32_t argc = args.Length(); int32_t i, j; for (i = 1; i < argc; i ++) { if (args[i]->IsArray()) { v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(args[i]); int32_t len = arr->Length(); for (j = 0; j < len; j ++) { v8::Local<v8::Value> k = arr->Get(j); if (obj->Has(k)) obj1->Set(k, obj->Get(k)); } } else { v8::Local<v8::Value> k = args[i]; if (obj->Has(k)) obj1->Set(k, obj->Get(k)); } } retVal = obj1; return 0; }
void V8HTMLMediaElement::controllerAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { MediaController* controller = 0; if (!value->IsNull()) { if (!V8MediaController::HasInstance(value, info.GetIsolate(), worldType(info.GetIsolate()))) { throwTypeError("Value is not of type MediaController", info.GetIsolate()); return; } controller = V8MediaController::toNative(value->ToObject()); } // 4.8.10.11.2 Media controllers: controller attribute. // On setting, it must first remove the element's mediagroup attribute, if any, HTMLMediaElement* imp = V8HTMLMediaElement::toNative(info.Holder()); imp->setMediaGroup(String()); // and then set the current media controller to the given value. imp->setController(controller); }
// static CJS_Value::Type CJS_Value::GetValueType(v8::Local<v8::Value> value) { if (value.IsEmpty()) return VT_unknown; if (value->IsString()) return VT_string; if (value->IsNumber()) return VT_number; if (value->IsBoolean()) return VT_boolean; if (value->IsDate()) return VT_date; if (value->IsObject()) return VT_object; if (value->IsNull()) return VT_null; if (value->IsUndefined()) return VT_undefined; return VT_unknown; }
result_t util_base::extend(v8::Local<v8::Value> v, const v8::FunctionCallbackInfo<v8::Value> &args, v8::Local<v8::Value> &retVal) { if (v->IsUndefined() || v->IsNull()) { retVal = v; return 0; } if (!v->IsObject()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Object> obj = v->ToObject(); int32_t argc = args.Length(); int32_t i, j; for (i = 1; i < argc; i ++) { v8::Local<v8::Value> val = args[i]; if (val->IsUndefined() || val->IsNull()) continue; if (!val->IsObject()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Object> obj1 = val->ToObject(); v8::Local<v8::Array> keys = obj1->GetPropertyNames(); int32_t len = keys->Length(); for (j = 0; j < len; j ++) { v8::Local<v8::Value> key = keys->Get(j); obj->Set(key, obj1->Get(key)); } } retVal = obj; return 0; }
void ConvertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject *owner, NPVariant* result) { VOID_TO_NPVARIANT(*result); // It is really the caller's responsibility to deal with the empty handle // case because there could be different actions to take in different // contexts. ASSERT(!object.IsEmpty()); if (object.IsEmpty()) return; if (object->IsNumber()) { DOUBLE_TO_NPVARIANT(object->NumberValue(), *result); } else if (object->IsBoolean()) { BOOLEAN_TO_NPVARIANT(object->BooleanValue(), *result); } else if (object->IsNull()) { NULL_TO_NPVARIANT(*result); } else if (object->IsUndefined()) { VOID_TO_NPVARIANT(*result); } else if (object->IsString()) { v8::Handle<v8::String> str = object->ToString(); uint16_t *buf = new uint16_t[str->Length()+1]; str->Write(buf); std::string utf8 = WideToUTF8(reinterpret_cast<wchar_t*>(buf)); char* utf8_chars = strdup(utf8.c_str()); STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result); delete[] buf; } else if (object->IsObject()) { WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(); NPObject* npobject = NPN_CreateScriptObject( 0, v8::Handle<v8::Object>::Cast(object), window); if (npobject) { _NPN_RegisterObject(npobject, owner); } OBJECT_TO_NPVARIANT(npobject, *result); } }
jobject TypeConverter::jsObjectToJavaKrollDict(JNIEnv *env, v8::Local<v8::Value> jsValue, bool *isNew) { if (jsValue->IsObject()) { v8::Handle<v8::Object> jsObject = jsValue->ToObject(); v8::Handle<v8::Array> objectKeys = jsObject->GetOwnPropertyNames(); int numKeys = objectKeys->Length(); *isNew = true; jobject javaKrollDict = env->NewObject(JNIUtil::krollDictClass, JNIUtil::krollDictInitMethod, numKeys); for (int i = 0; i < numKeys; i++) { v8::Local<v8::Value> jsObjectPropertyKey = objectKeys->Get((uint32_t) i); bool keyIsNew, valueIsNew; jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyKey, &keyIsNew); v8::Local<v8::Value> jsObjectPropertyValue = jsObject->Get(jsObjectPropertyKey); jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyValue, &valueIsNew); jobject result = env->CallObjectMethod(javaKrollDict, JNIUtil::krollDictPutMethod, javaObjectPropertyKey, javaObjectPropertyValue); env->DeleteLocalRef(result); if (keyIsNew) { env->DeleteLocalRef(javaObjectPropertyKey); } if (valueIsNew) { env->DeleteLocalRef(javaObjectPropertyValue); } } return javaKrollDict; } if (!jsValue->IsNull() && !jsValue->IsUndefined()) { LOGW(TAG, "jsObjectToJavaKrollDict returning null."); } return NULL; }
void V8Window::openerAttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { DOMWindow* imp = V8Window::toNative(info.Holder()); if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) return; // Opener can be shadowed if it is in the same domain. // Have a special handling of null value to behave // like Firefox. See bug http://b/1224887 & http://b/791706. if (value->IsNull()) { // imp->frame() cannot be null, // otherwise, SameOrigin check would have failed. ASSERT(imp->frame()); imp->frame()->loader()->setOpener(0); } // Delete the accessor from this object. info.Holder()->Delete(name); // Put property on the front (this) object. info.This()->Set(name, value); }
result_t util_base::omit(v8::Local<v8::Value> v, const v8::FunctionCallbackInfo<v8::Value> &args, v8::Local<v8::Object> &retVal) { Isolate* isolate = Isolate::current(); if (v->IsUndefined() || v->IsNull()) { retVal = v8::Object::New(isolate->m_isolate); return 0; } if (!v->IsObject()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Object> obj = v->ToObject(); std::map<std::string, bool> _map; int32_t argc = args.Length(); int32_t i, j; result_t hr; for (i = 1; i < argc; i ++) { if (args[i]->IsArray()) { v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(args[i]); int32_t len = arr->Length(); for (j = 0; j < len; j ++) { std::string k; hr = GetArgumentValue(arr->Get(j), k); if (hr < 0) return CHECK_ERROR(hr); _map.insert(std::pair<std::string, bool>(k, true)); } } else { std::string k; hr = GetArgumentValue(args[i], k); if (hr < 0) return CHECK_ERROR(hr); _map.insert(std::pair<std::string, bool>(k, true)); } } v8::Local<v8::Array> keys = obj->GetPropertyNames(); int32_t len = keys->Length(); v8::Local<v8::Object> obj1 = v8::Object::New(isolate->m_isolate); for (i = 0; i < len; i ++) { v8::Local<v8::Value> key = keys->Get(i); if (_map.find(*v8::String::Utf8Value(key)) == _map.end()) obj1->Set(key, obj->Get(key)); } retVal = obj1; return 0; }
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) { if(arg.IsEmpty() || arg->IsNull() || arg->IsUndefined()) { return NULL; } if(arg->IsArray()) { v8::Local<v8::Array> array = v8::Array::Cast(*arg); uint32_t arraySize = array->Length(); jclass objectClazz = env->FindClass("java/lang/Object"); jobjectArray result = env->NewObjectArray(arraySize, objectClazz, NULL); for(uint32_t i=0; i<arraySize; i++) { jobject val = v8ToJava(env, array->Get(i)); env->SetObjectArrayElement(result, i, val); } return result; } if(arg->IsString()) { v8::String::Utf8Value val(arg->ToString()); return env->NewStringUTF(*val); } if(arg->IsInt32() || arg->IsUint32()) { jint val = arg->ToInt32()->Value(); jclass clazz = env->FindClass("java/lang/Integer"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(I)V"); return env->NewObject(clazz, constructor, val); } if(arg->IsNumber()) { jdouble val = arg->ToNumber()->Value(); jclass clazz = env->FindClass("java/lang/Double"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(D)V"); return env->NewObject(clazz, constructor, val); } if(arg->IsBoolean()) { jboolean val = arg->ToBoolean()->Value(); jclass clazz = env->FindClass("java/lang/Boolean"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V"); return env->NewObject(clazz, constructor, val); } if(arg->IsObject()) { v8::Local<v8::Object> obj = v8::Object::Cast(*arg); v8::Local<v8::Value> isJavaObject = obj->GetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_OBJECT)); if(!isJavaObject.IsEmpty() && isJavaObject->IsBoolean()) { return v8ToJava_javaObject(env, obj); } v8::Local<v8::Value> isJavaLong = obj->GetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_LONG)); if(!isJavaLong.IsEmpty() && isJavaLong->IsBoolean()) { return v8ToJava_javaLong(env, obj); } } // TODO: handle other arg types v8::String::AsciiValue typeStr(arg); printf("v8ToJava: Unhandled type: %s\n", *typeStr); return NULL; }
PJsonVal TNodeJsUtil::GetObjJson(const v8::Local<v8::Value>& Val, const bool IgnoreFunc) { AssertR(!Val->IsExternal(), "TNodeJsUtil::GetObjJson: Cannot parse v8::External!"); if (Val->IsObject()) { // if we aren't ignoring functions and the object is a function // then throw an exception EAssertR(IgnoreFunc || !Val->IsFunction(), "TNodeJsUtil::GetObjJson: Cannot parse functions!"); // parse the object if (Val->IsFunction()) { return TJsonVal::New(); } else if (Val->IsBooleanObject()) { v8::Local<v8::BooleanObject> BoolObj = v8::Local<v8::BooleanObject>::Cast(Val); return TJsonVal::NewBool(BoolObj->ValueOf()); } else if (Val->IsNumberObject()) { return TJsonVal::NewNum(Val->NumberValue()); } else if (Val->IsStringObject() || Val->IsRegExp() || Val->IsDate()) { return TJsonVal::NewStr(TStr(*v8::String::Utf8Value(Val->ToString()))); } else if (Val->IsArray()) { PJsonVal JsonArr = TJsonVal::NewArr(); v8::Array* Arr = v8::Array::Cast(*Val); for (uint i = 0; i < Arr->Length(); i++) { if (!IgnoreFunc || !Arr->Get(i)->IsFunction()) { JsonArr->AddToArr(GetObjJson(Arr->Get(i), IgnoreFunc)); } } return JsonArr; } else { // general object with fields PJsonVal JsonVal = TJsonVal::NewObj(); v8::Local<v8::Object> Obj = Val->ToObject(); v8::Local<v8::Array> FldNmV = Obj->GetOwnPropertyNames(); for (uint i = 0; i < FldNmV->Length(); i++) { const TStr FldNm(*v8::String::Utf8Value(FldNmV->Get(i)->ToString())); v8::Local<v8::Value> FldVal = Obj->Get(FldNmV->Get(i)); if (!IgnoreFunc || !FldVal->IsFunction()) { JsonVal->AddToObj(FldNm, GetObjJson(FldVal, IgnoreFunc)); } } return JsonVal; } } else { // primitive if (Val->IsUndefined()) { return TJsonVal::New(); } else if (Val->IsNull()) { return TJsonVal::NewNull(); } else if (Val->IsBoolean()) { return TJsonVal::NewBool(Val->BooleanValue()); } else if (Val->IsNumber()) { return TJsonVal::NewNum(Val->NumberValue()); } else if (Val->IsString()) { return TJsonVal::NewStr(TStr(*v8::String::Utf8Value(Val->ToString()))); } else { // TODO check for v8::Symbol throw TExcept::New("TNodeJsUtil::GetObjJson: Unknown v8::Primitive type!"); } } }
inline bool isUndefined(v8::Local<v8::Value> value) { Nan::HandleScope scope; return value->IsUndefined() || value->IsNull(); }
// converts js value to java object and recursively converts sub objects if this // object is a container type jobject TypeConverter::jsValueToJavaObject(v8::Local<v8::Value> jsValue, bool *isNew) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } if (jsValue->IsNumber()) { *isNew = true; if (jsValue->IsInt32()) { jint javaInt = TypeConverter::jsNumberToJavaInt(jsValue->ToNumber()); return env->NewObject(JNIUtil::integerClass, JNIUtil::integerInitMethod, javaInt); } jdouble javaDouble = TypeConverter::jsNumberToJavaDouble(jsValue->ToNumber()); return env->NewObject(JNIUtil::doubleClass, JNIUtil::doubleInitMethod, javaDouble); } else if (jsValue->IsBoolean()) { jboolean javaBoolean = TypeConverter::jsBooleanToJavaBoolean(jsValue->ToBoolean()); *isNew = true; return env->NewObject(JNIUtil::booleanClass, JNIUtil::booleanInitMethod, javaBoolean); } else if (jsValue->IsString()) { *isNew = true; return TypeConverter::jsStringToJavaString(jsValue->ToString()); } else if (jsValue->IsDate()) { Local<Date> date = Local<Date>::Cast<Value>(jsValue); return TypeConverter::jsDateToJavaDate(date); } else if (jsValue->IsArray()) { *isNew = true; return TypeConverter::jsArrayToJavaArray(v8::Handle<v8::Array>::Cast(jsValue)); } else if (jsValue->IsFunction()) { *isNew = true; return TypeConverter::jsObjectToJavaFunction(jsValue->ToObject()); } else if (jsValue->IsObject()) { v8::Handle<v8::Object> jsObject = jsValue->ToObject(); if (JavaObject::isJavaObject(jsObject)) { *isNew = JavaObject::useGlobalRefs ? false : true; JavaObject *javaObject = JavaObject::Unwrap<JavaObject>(jsObject); return javaObject->getJavaObject(); } else { v8::Handle<v8::Array> objectKeys = jsObject->GetOwnPropertyNames(); int numKeys = objectKeys->Length(); *isNew = true; jobject javaHashMap = env->NewObject(JNIUtil::hashMapClass, JNIUtil::hashMapInitMethod, numKeys); for (int i = 0; i < numKeys; i++) { v8::Local<v8::Value> jsObjectPropertyKey = objectKeys->Get((uint32_t) i); bool keyIsNew, valueIsNew; jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(jsObjectPropertyKey, &keyIsNew); v8::Local<v8::Value> jsObjectPropertyValue = jsObject->Get(jsObjectPropertyKey); jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(jsObjectPropertyValue, &valueIsNew); jobject result = env->CallObjectMethod(javaHashMap, JNIUtil::hashMapPutMethod, javaObjectPropertyKey, javaObjectPropertyValue); env->DeleteLocalRef(result); if (keyIsNew) { env->DeleteLocalRef(javaObjectPropertyKey); } if (valueIsNew) { env->DeleteLocalRef(javaObjectPropertyValue); } } return javaHashMap; } } if (!jsValue->IsNull() && !jsValue->IsUndefined()) { LOGW(TAG, "jsValueToJavaObject returning null."); } return NULL; }
result_t util_base::isNullOrUndefined(v8::Local<v8::Value> v, bool& retVal) { retVal = v->IsNull() || v->IsUndefined(); return 0; }
result_t util_base::isNull(v8::Local<v8::Value> v, bool& retVal) { retVal = v->IsNull(); return 0; }
std::unique_ptr<protocol::Value> toProtocolValue(v8::Local<v8::Context> context, v8::Local<v8::Value> value, int maxDepth) { if (value.IsEmpty()) { NOTREACHED(); return nullptr; } if (!maxDepth) return nullptr; maxDepth--; if (value->IsNull() || value->IsUndefined()) return protocol::Value::null(); if (value->IsBoolean()) return protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value()); if (value->IsNumber()) return protocol::FundamentalValue::create(value.As<v8::Number>()->Value()); if (value->IsString()) return protocol::StringValue::create(toProtocolString(value.As<v8::String>())); if (value->IsArray()) { v8::Local<v8::Array> array = value.As<v8::Array>(); std::unique_ptr<protocol::ListValue> inspectorArray = protocol::ListValue::create(); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; i++) { v8::Local<v8::Value> value; if (!array->Get(context, i).ToLocal(&value)) return nullptr; std::unique_ptr<protocol::Value> element = toProtocolValue(context, value, maxDepth); if (!element) return nullptr; inspectorArray->pushValue(std::move(element)); } return std::move(inspectorArray); } if (value->IsObject()) { std::unique_ptr<protocol::DictionaryValue> jsonObject = protocol::DictionaryValue::create(); v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); v8::Local<v8::Array> propertyNames; if (!object->GetPropertyNames(context).ToLocal(&propertyNames)) return nullptr; uint32_t length = propertyNames->Length(); for (uint32_t i = 0; i < length; i++) { v8::Local<v8::Value> name; if (!propertyNames->Get(context, i).ToLocal(&name)) return nullptr; // FIXME(yurys): v8::Object should support GetOwnPropertyNames if (name->IsString()) { v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(context, v8::Local<v8::String>::Cast(name)); if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust()) continue; } v8::Local<v8::String> propertyName; if (!name->ToString(context).ToLocal(&propertyName)) continue; v8::Local<v8::Value> property; if (!object->Get(context, name).ToLocal(&property)) return nullptr; std::unique_ptr<protocol::Value> propertyValue = toProtocolValue(context, property, maxDepth); if (!propertyValue) return nullptr; jsonObject->setValue(toProtocolString(propertyName), std::move(propertyValue)); } return std::move(jsonObject); } NOTREACHED(); return nullptr; }