void NativeScriptRuntime::RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
{
	SET_PROFILER_FRAME();

	ASSERT_MESSAGE(args.Length() == 2, "require should be called with two parameters");
	ASSERT_MESSAGE(!args[0]->IsUndefined() && !args[0]->IsNull(), "require called with undefined moduleName parameter");
	ASSERT_MESSAGE(!args[1]->IsUndefined() && !args[1]->IsNull(), "require called with undefined callingModulePath parameter");
	ASSERT_MESSAGE(args[0]->IsString(), "require should be called with string parameter");
	ASSERT_MESSAGE(args[1]->IsString(), "require should be called with string parameter");

	string moduleName = ConvertToString(args[0].As<String>());
	string callingModuleDirName = ConvertToString(args[1].As<String>());

	JEnv env;
	JniLocalRef jsModulename(env.NewStringUTF(moduleName.c_str()));
	JniLocalRef jsCallingModuleDirName(env.NewStringUTF(callingModuleDirName.c_str()));
	JniLocalRef jsModulePath(env.CallStaticObjectMethod(RequireClass, GET_MODULE_PATH_METHOD_ID, (jstring) jsModulename, (jstring) jsCallingModuleDirName));

	auto isolate = Isolate::GetCurrent();

	// cache the required modules by full path, not name only, since there might be some collisions with relative paths and names
	string modulePath = ArgConverter::jstringToString((jstring) jsModulePath);
	if(modulePath == ""){
		// module not found
		stringstream ss;
		ss << "Module \"" << moduleName << "\" not found";
		string exception = ss.str();
		ExceptionUtil::GetInstance()->ThrowExceptionToJs(exception);
		return;
	}
	if (modulePath == "EXTERNAL_FILE_ERROR")
	{
		// module not found
		stringstream ss;
		ss << "Module \"" << moduleName << "\" is located on the external storage. Modules can be private application files ONLY";
		string exception = ss.str();
		ExceptionUtil::GetInstance()->ThrowExceptionToJs(exception);
		return;
	}

	auto it = loadedModules.find(modulePath);

	Handle<Object> moduleObj;
	bool hasError = false;

	if (it == loadedModules.end())
	{
		CompileAndRun(modulePath, hasError, moduleObj, false/*is bootstrap call*/);
	}
	else
	{
		moduleObj = Local<Object>::New(isolate, *((*it).second));
	}

	if(!hasError){
		args.GetReturnValue().Set(moduleObj);
	}
}
vector<string> NativeScriptRuntime::GetTypeMetadata(const string& name, int index)
{
	JEnv env;

	string canonicalName = Util::ConvertFromJniToCanonicalName(name);

	JniLocalRef className(env.NewStringUTF(canonicalName.c_str()));
	jint idx = index;

	JniLocalRef pubApi(env.CallStaticObjectMethod(PlatformClass, GET_TYPE_METADATA, (jstring) className, idx));

	jsize length = env.GetArrayLength(pubApi);

	assert(length > 0);

	vector<string> result;

	for (jsize i=0; i<length; i++)
	{
		JniLocalRef s(env.GetObjectArrayElement(pubApi, i));
		const char *pc = env.GetStringUTFChars(s, nullptr);
		result.push_back(string(pc));
		env.ReleaseStringUTFChars(s, pc);
	}

	return result;
}
jclass NativeScriptRuntime::ResolveClass(const std::string& fullClassname, const Local<Object>& implementationObject) {

	auto itFound = s_classCache.find(fullClassname);

	jclass globalRefToGeneratedClass;

	if (itFound != s_classCache.end())
	{
		globalRefToGeneratedClass = itFound->second;
	}
	else
	{
		JEnv env;

		//get needed arguments in order to load binding
		JniLocalRef javaFullClassName(env.NewStringUTF(fullClassname.c_str()));

		jobjectArray methodOverrides = GetMethodOverrides(env, implementationObject);

		//create or load generated binding (java class)
		JniLocalRef generatedClass(env.CallStaticObjectMethod(PlatformClass, RESOLVE_CLASS_METHOD_ID,  (jstring)javaFullClassName, methodOverrides));
		globalRefToGeneratedClass = reinterpret_cast<jclass>(env.NewGlobalRef(generatedClass));

		s_classCache.insert(make_pair(fullClassname, globalRefToGeneratedClass));
	}

	return globalRefToGeneratedClass;
}
void NativeScriptRuntime::APP_FAIL(const char *message)
{
	//ASSERT_FAIL(message);

	JEnv env;
	jstring msg = env.NewStringUTF(message);
	env.CallStaticVoidMethod(PlatformClass, APP_FAIL_METHOD_ID, msg);
}
Esempio n. 5
0
/* *
 * private method that takes debug message as json from v8
 * after it gets the message the message handler passes it to enqueueMessage method in java
 */
void JsDebugger::MyMessageHandler(const v8::Debug::Message& message)
{
	if (s_jsDebugger == nullptr)
	{
		return;
	}

	auto json = message.GetJSON();
	auto str = ConvertToString(json);

	JEnv env;
	JniLocalRef s(env.NewStringUTF(str.c_str()));
	env.CallVoidMethod(s_jsDebugger, s_EnqueueMessage, (jstring) s);
}
jclass NativeScriptRuntime::ResolveClass(const std::string& fullClassname, const Handle<Object>& implementationObject) {

	JEnv env;

	//get needed arguments in order to load binding
	JniLocalRef javaFullClassName(env.NewStringUTF(fullClassname.c_str()));

	jobjectArray methodOverrides = GetMethodOverrides(env, implementationObject);

	//create or load generated binding (java class)
	JniLocalRef generatedClass(env.CallStaticObjectMethod(PlatformClass, RESOLVE_CLASS_METHOD_ID,  (jstring)javaFullClassName, methodOverrides));
	jclass globalRefToGeneratedClass = reinterpret_cast<jclass>(env.NewGlobalRef(generatedClass));

	return globalRefToGeneratedClass;
}
//delete the returned local reference after use
jobjectArray NativeScriptRuntime::GetMethodOverrides(JEnv& env, const Local<Object>& implementationObject)
{
	if (implementationObject.IsEmpty())
	{
		return JavaObjectArrayCache::GetJavaStringArray(0);
	}

	vector<jstring> methodNames;
	auto propNames = implementationObject->GetOwnPropertyNames();
	for (int i = 0; i < propNames->Length(); i++)
	{
		auto name = propNames->Get(i).As<String>();
		auto method = implementationObject->Get(name);

		bool methodFound = !method.IsEmpty() && method->IsFunction();

		if (methodFound)
		{
			String::Utf8Value stringValue(name);
			jstring value = env.NewStringUTF(*stringValue);
			methodNames.push_back(value);
		}
	}

	int methodCount = methodNames.size();

	jobjectArray methodOverrides = JavaObjectArrayCache::GetJavaStringArray(methodCount);
	for (int i = 0; i < methodCount; i++)
	{
		env.SetObjectArrayElement(methodOverrides, i, methodNames[i]);
	}

	for (int i = 0; i < methodCount; i++)
	{
		env.DeleteLocalRef(methodNames[i]);
	}

	return methodOverrides;
}
Handle<Object> NativeScriptRuntime::FindClass(const string& className)
{
	Handle<Object> clazz;
	JEnv env;

	jmethodID mid = env.GetStaticMethodID(PlatformClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
	assert(mid != nullptr);
	JniLocalRef name(env.NewStringUTF(className.c_str()));
	jclass c = (jclass)env.CallStaticObjectMethod(PlatformClass, mid, (jstring)name);
	if (env.ExceptionCheck() == JNI_FALSE)
	{
		jint javaObjectID = objectManager->GetOrCreateObjectId(c);
		clazz = objectManager->GetJsObjectByJavaObject(javaObjectID);

		if (clazz.IsEmpty())
		{
			clazz = objectManager->CreateJSWrapper(javaObjectID, "Ljava/lang/Class;", c);
		}

		env.DeleteLocalRef(c);
	}
	return clazz;
}
Esempio n. 9
0
void FieldAccessor::SetJavaField(Isolate *isolate, const Local<Object>& target, const Local<Value>& value, FieldCallbackData *fieldData)
{
	JEnv env;

	HandleScope handleScope(isolate);
	auto runtime = Runtime::GetRuntime(isolate);
	auto objectManager = runtime->GetObjectManager();

	JniLocalRef targetJavaObject;

	const auto& fieldTypeName = fieldData->signature;
	auto isStatic = fieldData->isStatic;

	auto isPrimitiveType = fieldTypeName.size() == 1;
	auto isFieldArray = fieldTypeName[0] == '[';

	if (fieldData->fid == nullptr)
	{
		auto fieldJniSig = isPrimitiveType
							? fieldTypeName
								:
								(isFieldArray
									? fieldTypeName
										:
										("L" + fieldTypeName + ";"));

		if (isStatic)
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
		else
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
	}

	if (!isStatic)
	{
		targetJavaObject = objectManager->GetJavaObjectByJsObject(target);

		if (targetJavaObject.IsNull())
		{
			stringstream ss;
			ss << "Cannot access property '" << fieldData->name << "' because there is no corresponding Java object";
			throw NativeScriptException(ss.str());
		}
	}

	auto fieldId = fieldData->fid;
	auto clazz = fieldData->clazz;

	if (isPrimitiveType)
	{
		switch (fieldTypeName[0])
		{
			case 'Z': //bool
			{
				//TODO: validate value is a boolean before calling
				if (isStatic)
				{
					env.SetStaticBooleanField(clazz, fieldId, value->BooleanValue());
				}
				else
				{
					env.SetBooleanField(targetJavaObject, fieldId, value->BooleanValue());
				}
				break;
			}
			case 'B': //byte
			{
				//TODO: validate value is a byte before calling
				if (isStatic)
				{
					env.SetStaticByteField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetByteField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'C': //char
			{
				//TODO: validate value is a single char
				String::Utf8Value stringValue(value->ToString());
				JniLocalRef value(env.NewStringUTF(*stringValue));
				const char* chars = env.GetStringUTFChars(value, 0);

				if (isStatic)
				{
					env.SetStaticCharField(clazz, fieldId, chars[0]);
				}
				else
				{
					env.SetCharField(targetJavaObject, fieldId, chars[0]);
				}
				env.ReleaseStringUTFChars(value, chars);
				break;
			}
			case 'S': //short
			{
				//TODO: validate value is a short before calling
				if (isStatic)
				{
					env.SetStaticShortField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetShortField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'I': //int
			{
				//TODO: validate value is a int before calling
				if (isStatic)
				{
					env.SetStaticIntField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetIntField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;

			}
			case 'J': //long
			{
				jlong longValue = static_cast<jlong>(ArgConverter::ConvertToJavaLong(value));
				if (isStatic)
				{
					env.SetStaticLongField(clazz, fieldId, longValue);
				}
				else
				{
					env.SetLongField(targetJavaObject, fieldId, longValue);
				}
				break;
			}
			case 'F': //float
			{
				if (isStatic)
				{
					env.SetStaticFloatField(clazz, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				else
				{
					env.SetFloatField(targetJavaObject, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				break;
			}
			case 'D': //double
			{
				if (isStatic)
				{
					env.SetStaticDoubleField(clazz, fieldId, value->NumberValue());
				}
				else
				{
					env.SetDoubleField(targetJavaObject, fieldId, value->NumberValue());
				}
				break;
			}
			default:
				{
		stringstream ss;
				ss << "(InternalError): in FieldAccessor::SetJavaField: Unknown field type: '" << fieldTypeName[0] << "'";
				throw NativeScriptException(ss.str());
			}
		}
	}
	else
	{
		bool isString = fieldTypeName == "java/lang/String";
		JniLocalRef result;

		if (!value->IsNull())
		{
			if (isString)
			{
				//TODO: validate valie is a string;
				result = ConvertToJavaString(value);
			}
			else
			{
				auto objectWithHiddenID = value->ToObject();
				result = objectManager->GetJavaObjectByJsObject(objectWithHiddenID);
			}
		}

		if (isStatic)
		{
			env.SetStaticObjectField(clazz, fieldId, result);
		}
		else
		{
			env.SetObjectField(targetJavaObject, fieldId, result);
		}
	}
}
void FieldAccessor::SetJavaField(const Local<Object>& target, const Local<Value>& value, FieldCallbackData *fieldData)
{
	JEnv env;

	auto isolate = Isolate::GetCurrent();
	HandleScope handleScope(isolate);

	jweak targetJavaObject;

	const auto& fieldTypeName = fieldData->signature;
	auto isStatic = fieldData->isStatic;

	auto isPrimitiveType = fieldTypeName.size() == 1;
	auto isFieldArray = fieldTypeName[0] == '[';


	if (fieldData->fid == nullptr)
	{
		auto fieldJniSig = isPrimitiveType
								? fieldTypeName
								: (isFieldArray
									? fieldTypeName
									: ("L" + fieldTypeName + ";"));

		if (isStatic)
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
		else
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
	}

	if (!isStatic)
	{
		targetJavaObject = objectManager->GetJavaObjectByJsObject(target);
	}

	auto fieldId = fieldData->fid;
	auto clazz = fieldData->clazz;

	if (isPrimitiveType)
	{
		switch (fieldTypeName[0])
		{
			case 'Z': //bool
			{
				//TODO: validate value is a boolean before calling
				if (isStatic)
				{
					env.SetStaticBooleanField(clazz, fieldId, value->BooleanValue());
				}
				else
				{
					env.SetBooleanField(targetJavaObject, fieldId, value->BooleanValue());
				}
				break;
			}
			case 'B': //byte
			{
				//TODO: validate value is a byte before calling
				if (isStatic)
				{
					env.SetStaticByteField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetByteField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'C': //char
			{
				//TODO: validate value is a single char
				String::Utf8Value stringValue(value->ToString());
				JniLocalRef value(env.NewStringUTF(*stringValue));
				const char* chars = env.GetStringUTFChars(value, 0);

				if (isStatic)
				{
					env.SetStaticCharField(clazz, fieldId, chars[0]);
				}
				else
				{
					env.SetCharField(targetJavaObject, fieldId, chars[0]);
				}
				env.ReleaseStringUTFChars(value, chars);
				break;
			}
			case 'S': //short
			{
				//TODO: validate value is a short before calling
				if (isStatic)
				{
					env.SetStaticShortField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetShortField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'I': //int
			{
				//TODO: validate value is a int before calling
				if (isStatic)
				{
					env.SetStaticIntField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetIntField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;

			}
			case 'J': //long
			{
				jlong longValue = static_cast<jlong>(ArgConverter::ConvertToJavaLong(value));
				if (isStatic)
				{
					env.SetStaticLongField(clazz, fieldId, longValue);
				}
				else
				{
					env.SetLongField(targetJavaObject, fieldId, longValue);
				}
				break;
			}
			case 'F': //float
			{
				if (isStatic)
				{
					env.SetStaticFloatField(clazz, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				else
				{
					env.SetFloatField(targetJavaObject, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				break;
			}
			case 'D': //double
			{
				if (isStatic)
				{
					env.SetStaticDoubleField(clazz, fieldId, value->NumberValue());
				}
				else
				{
					env.SetDoubleField(targetJavaObject, fieldId, value->NumberValue());
				}
				break;
			}
			default:
			{
				// TODO:
				ASSERT_FAIL("Unknown field type");
				break;
			}
		}
	}
	else
	{
		bool isString = fieldTypeName == "java/lang/String";
		jobject result = nullptr;

		if(!value->IsNull()) {
			if (isString)
			{
				//TODO: validate valie is a string;
				result = ConvertToJavaString(value);
			}
			else
			{
				auto objectWithHiddenID = value->ToObject();
				result =objectManager->GetJavaObjectByJsObject(objectWithHiddenID);
			}
		}

		if (isStatic)
		{
			env.SetStaticObjectField(clazz, fieldId, result);
		}
		else
		{
			env.SetObjectField(targetJavaObject, fieldId, result);
		}

		if (isString)
		{
			env.DeleteLocalRef(result);
		}
	}
}
Esempio n. 11
0
void JsDebugger::ConsoleMessage(const v8::FunctionCallbackInfo<v8::Value>& args)
{
	if ((args.Length() > 0) && args[0]->IsString())
	{
		std::string message = ConvertToString(args[0]->ToString());
		//jboolean isError = (jboolean) = args[1]->ToBoolean()->BooleanValue();


		std:string level = "log";
		if (args.Length() > 1  && args[1]->IsString())
		{
			level = ConvertToString(args[1]->ToString());
		}

		string srcFileName = "";
		int lineNumber = 0;
		int columnNumber = 0;

		auto stackTrace = StackTrace::CurrentStackTrace(Isolate::GetCurrent(), 2, StackTrace::kOverview);
		if (!stackTrace.IsEmpty())
		{
			auto frame = stackTrace->GetFrame(1);
			if (!frame.IsEmpty())
			{
				auto scriptName = frame->GetScriptName();
				if (!scriptName.IsEmpty())
				{
					srcFileName = ConvertToString(scriptName);
				}

				lineNumber = frame->GetLineNumber();
				columnNumber = frame->GetColumn();
			}
		}




		//    			var consoleEvent = {
		//	    			"seq":0,
		//	    			"type":"event",
		//	    			"event":"messageAdded",
		//	    			"success":true,
		//	    			"body":
		//	    			{
		//	    				"message":
		//	    				{
		//	    			        "source":"console-api",
		//	    			        "type": "log",
		//	    			        "level": 'error',
		//	    			        "line": 0,
		//	    			        "column": 0,
		//	    			        "url": "",
		//	    			        "groupLevel": 7,
		//	    			        "repeatCount": 1,
		//	    			        "text": "My message"
		//	    			    }
		//	    			}
		//    			};

		stringstream consoleEventSS;
		consoleEventSS << "{\"seq\":0, \"type\":\"event\", \"event\":\"messageAdded\", \"success\":true, \"body\": { \"message\": { \"source\":\"console-api\", "
				<< " \"type\": \"log\","
				<< " \"level\": \"" << level << "\", "
				<< " \"line\": " << lineNumber << ","
				<< " \"column\": " << columnNumber << ","
				<< " \"url\" : \"" << srcFileName << "\","
				<< " \"groupLevel\": 7, \"repeatCount\": 1, "
				<< " \"text\": \"" << message << "\" } } }";


		JEnv env;
		JniLocalRef s(env.NewStringUTF(consoleEventSS.str().c_str()));
		env.CallVoidMethod(s_jsDebugger, s_EnqueueMessage, (jstring) s);
	}
}
Esempio n. 12
0
void Module::RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
{
	try
	{
		auto isolate = Isolate::GetCurrent();

		if (args.Length() != 2)
		{
			throw NativeScriptException(string("require should be called with two parameters"));
		}
		if (!args[0]->IsString())
		{
			throw NativeScriptException(string("require's first parameter should be string"));
		}
		if (!args[1]->IsString())
		{
			throw NativeScriptException(string("require's second parameter should be string"));
		}

		string moduleName = ConvertToString(args[0].As<String>());
		string callingModuleDirName = ConvertToString(args[1].As<String>());

		JEnv env;
		JniLocalRef jsModulename(env.NewStringUTF(moduleName.c_str()));
		JniLocalRef jsCallingModuleDirName(env.NewStringUTF(callingModuleDirName.c_str()));
		JniLocalRef jsModulePath(env.CallStaticObjectMethod(MODULE_CLASS, RESOLVE_PATH_METHOD_ID, (jstring) jsModulename, (jstring) jsCallingModuleDirName));

		// cache the required modules by full path, not name only, since there might be some collisions with relative paths and names
		string modulePath = ArgConverter::jstringToString((jstring) jsModulePath);

		auto isData = false;

		auto moduleObj = Load(modulePath, isData);

		if (isData)
		{
			assert(!moduleObj.IsEmpty());

			args.GetReturnValue().Set(moduleObj);
		}
		else
		{
			auto exportsObj = moduleObj->Get(ConvertToV8String("exports"));

			assert(!exportsObj.IsEmpty());

			args.GetReturnValue().Set(exportsObj);
		}
	}
	catch (NativeScriptException& e)
	{
		e.ReThrowToV8();
	}
	catch (std::exception e) {
				stringstream ss;
		ss << "Error: c++ exception: " << e.what() << endl;
		NativeScriptException nsEx(ss.str());
		nsEx.ReThrowToV8();
	}
	catch (...) {
		NativeScriptException nsEx(std::string("Error: c++ exception!"));
		nsEx.ReThrowToV8();
	}
}