Trans ignore some classes methods (HTML 5)

Monkey Forums/Monkey Bug Reports/Trans ignore some classes methods (HTML 5)

Rushino(Posted 2013) [#1]
Hi,

Mark i am calling out for your help.

Ive just discovered a major flaw in my project. My project is rather big but this shouldn't cause this to be honest. It seem to be a Trans bug to me.. at first sight or is there something i am not aware of ?

I have 4 classes that inherit from a base class.

While testing on html 5... 2 of theses classes do not enter in their overrided methods, the base methods was used instead. I didn't understand why... but it worked for XNA platform. While checking for the XNA source code ive discovered that everything was normal while debugging.. the correct methods are executed from the parent class but in html 5... thoses classes was generated but the methods was not. Only 2 of thoses classes had their methods generated which probably explain why the base class is used instead. The classes methods definitions wasn't there... i posted the whole code in monkey and the code that was generated to help out. I would be glad to discover what happen really.

******* Here the both classes that working *******

DoConnectionTask (Monkey code)


DoConnectionTask (HTML 5 code)


DoAuthenticationTask (Monkey code)


DoAuthenticationTask (HTML 5 code)


******* Here the both classes that NOT working, adding new ones also doesn't work *******

DoHandleUpdateTestTask (Monkey code)


DoHandleUpdateTestTask (HTML 5 code)


c_DoGetMenuPlayerDataTask (Monkey code)


c_DoGetMenuPlayerDataTask (HTML 5 code)


I was looking for something like... but it was not found.

c_DoGetMenuPlayerDataTask.prototype.p_StartCondition=function(){
...
}

Also apply to DoHandleUpdateTestTask... not found either

c_DoHandleUpdateTestTask.prototype.p_StartCondition=function(){
...
}

Do you have any ideas what could cause this ? I am using JungleIDE but i don't think at all this could be the cause.. but its worth mentionning.

It is possible also that this is due to the imports ? i doubt since the two classes that are working are on the same level.

I am using monkey69.

Thanks a lots for your help.


slenkar(Posted 2013) [#2]
I think its because of the 'unreachable code' algorithm
cutting out the code from being translated.

If you include the code with reflection the code it will be added.


Rushino(Posted 2013) [#3]
How do i do that ? I need reflecrion filter for theses classes?


Rushino(Posted 2013) [#4]
Damn. I just tested your solution and it work perfectly now... strange. This can lead to lots of confusion is there a way to determine when exactly we need to put our classes in the reflection filter ? or do you suggest to pass all the classes to the filter ? i wanted to avoid this because of the overhead this can cause.. it seem like that everythink that require some class extends need it.

Anyway thanks a lots for your help really appreciated!


slenkar(Posted 2013) [#5]
Its trial and error really, as this is a bug.

Reflecting every class would create loads of code and slow down compilation. Dunno how it effects game speed.

All this could be solved by turning off the algorithm that excludes 'unreachable code'


Rushino(Posted 2013) [#6]
Mark, what your opinion on this ?


marksibly(Posted 2013) [#7]
Can you post something I can actually run - ie: reduce it down to a minimal example?

If it's something to do with dead code elimination, it's probably to do with how objects are created and/or how methods are called, and you haven't shown any of that.

But if it's working on XNA but not html5, that's esp. weird as the code elimination is target-independent.


Rushino(Posted 2013) [#8]
I made one but i deleted it.. since the sample was fully working without problems which is kind of odd. But i had put the tasks in the same main class module so maybe that explain why it was working. I will try to get something for you tomorrow.

What slenkar suggested worked so this have to do with reflection or something...

I am 100% sure that its working on XNA but not HTML 5.

Here i posted the complete class of tasks handling that show how methods are called but i doubt it will help. Basically i use RegisterTask to register a task (class based on Task object) this add the task to an internal list. Then i call methods StartCondition etc.. with IF statements. The idea of a Task is to be run using a start condition, end condition and with support of callbacks for post-operations. This include Task, TasksHandler and other dependent classes. UpdateTasks:Void is what update the tasks... this is called in the OnUpdate method normally. There also a RenderTasks for tasks associated to rendering.

Strict

Import mojo

'summary: Gestionnaire de tâches.
Class TasksHandler

Private

	Field tasksList:IntMap<Task>

Public
	
	'summary: Créer une gestionnaire de tâches.
	Method New()
		tasksList = New IntMap<Task>()
	End
	
	'summary: Enregistrer une tâche dans le gestionnaire.
	Method RegisterTask:Void(task:Task)
		If Not tasksList.Contains(task.taskId)
			tasksList.Add(task.taskId, task)
		End If
	End
	
	'summary: Terminer la tâche (avec erreur) à partir de son identifiant de la liste de tâche.
	Method TerminateTask:Void(taskId:Int, hasErrors:Bool, errorCode:Int, reason:String)
		If Self.tasksList.Contains(taskId) Then
			Local t:Task = Self.tasksList.Get(taskId)
			t.Terminate(hasErrors, errorCode, reason)
		Else
			Error("The task with ID " + taskId + " are not active in the task list!")
		End If
	End
	
	'summary: Terminer la tâche (sans erreur) à partir de son identifiant de la liste de tâche.
	Method TerminateTask:Void(taskId:Int)
		If Self.tasksList.Contains(taskId) Then
			Local t:Task = Self.tasksList.Get(taskId)
			t.Terminate(False, -1, "Task terminated normally.")
		Else
			Error("The task with ID " + taskId + " are not active in the task list!")
		End If
	End
	
	'summary: Obtenir la tâche à partir de son identifiant.
	Method GetTask:Task(taskId:Int)
		Return Self.tasksList.Get(taskId)
	End
	
	'summary: Déterminer si la tâche est toujours active.
	Method TaskIsActive:Bool(taskId:Int)
		Local result:Bool = False
		If Self.tasksList.Contains(taskId) Then
			result = Self.tasksList.Get(taskId).IsStillActive()
		End If
		Return result
	End
	
	'summary: Obtenir le nombre de tâches enregistrées.
	Method GetNbOfTasks:Int()
		Return tasksList.Count()
	End
	
	'summary: Mettre à jour les tâches.
	Method UpdateTasks:Void()

		For Local n:= EachIn tasksList
	
			Local t:Task = n.Value
			Local taskSettings:TaskSettings = t.settings

			' Vérifier si la condition de fin a été remplie et marquer la tâche comme étant complété
			' si c'est le cas.
			If t.CompleteCondition() Then

				' Marquer la tâche comme complété.
				t.isFinished = True
				
			ElseIf t.ErrorCondition() Then	' Vérifier si la condition d'erreur est remplie.

				' Marquer la tâche comme complété.
				t.isFinished = True

				' Marquer la tâche comme étant en erreur.
				If Not t.hasErrors Then t.hasErrors = True
			
			End If

			' Déterminer si la tâche est terminée. Si OUI alors éxécuter les événements de fin de tâche.
			If t.isFinished Then

				' Éxécuter l'événement de fin de tâche.
				If Not t.hasErrors
					t.TaskCompleted()
				Else
					t.TaskError(t.terminateReason, t.errorCode)
				End If
					
				' Retirer la tâche de la liste de tâches.
				Self.tasksList.Remove(t.taskId)
				
			Else
			
				' Déterminer si la condition de départ est remplie ainsi que le délai de démarrage requis pour 
				' démarrer la tâche sinon passer à la suivante.
				Local startDelayPassed:Bool = t.startedTime + taskSettings.startDelay <= Millisecs()
				If t.StartCondition() And startDelayPassed Then
					t.isStarted = True
				End
				
				' Éxécuter les opérations de la tâches si elle est démarré.
				If t.isStarted Then
					
					' Vérifier s'il faut que la condition de départ soit vérifier au début de l'éxécution.
					Local canProceedExecution:Bool = True
					If t.settings.checkStartConditionEachTime Then
						canProceedExecution = t.StartCondition()
					End If
					
					If canProceedExecution Then
					
						' S'il s'agit de la première éxécution, on détermine le temps actuel de l'éxécution.
						If t.lastExecutionTime = 0 Then
							t.lastExecutionTime = Millisecs()
						End If
						
						' Déterminer si on doit vérifier la condition de départ avant l'éxécution.
						' Si OUI alors on vérifie la condition de départ et si on a dépassé le délai d'éxécution requis pour 
						' déterminé si on peut démarré l'éxécution de la tâche sinon on fait juste vérifié si on a dépassé
						' le délai d'éxécution requis pour démarrer l'éxécution de la tâche.
						Local canStartExecution:Bool = True
						Local executionDelayPassed:Bool = t.lastExecutionTime + taskSettings.executionDelay <= Millisecs()
						If taskSettings.checkStartConditionEachTime = True Then
							canStartExecution = t.StartCondition() And executionDelayPassed And t.nbOfExecution < t.settings.maxNbOfExecution
						Else
							canStartExecution = executionDelayPassed And t.nbOfExecution < t.settings.maxNbOfExecution
						End If
						
						' Déterminer si ont peut démarré l'éxécution de la tâche.
						If canStartExecution Then
							
							' Déterminer le dernier temps d'éxécution.
							t.lastExecutionTime = Millisecs()
							
							' Éxécuter la tâche.
							t.Execute()
							
							' Incrémenté le nombre d'éxécution.
							t.nbOfExecution = t.nbOfExecution + 1
					
						End If
					
					End If
			
				End If
			
			End If

		Next
		
	End
	
	'summary: Afficher le rendu des tâches démarrées.
	Method RenderTasks:Void()
		For Local n:= EachIn tasksList
			Local t:Task = n.Value
			If t.isStarted Then
				t.Render()
			End If
		Next
	End
	
	'summary: Effacer les tâches en cours.
	Method ClearTasks:Void()
		tasksList.Clear()
	End
	
End

'summary: Représente les paramètres pour une tâche.
Class TaskSettings

Private

	Field maxNbOfExecution:Int
	Field checkStartConditionEachTime:Bool
	Field startDelay:Int
	Field executionDelay:Int
	Field expirationDelay:Int
	
Public

	Const ONE_TIME_EXECUTION:Int = 1
	Const NO_DELAY:Int = 0
	Const DEFAULT_EXPIRATION_DELAY:Int = 15
	Const NO_EXPIRATION:Int = -1
	
	Method New()
		Self.maxNbOfExecution = TaskSettings.ONE_TIME_EXECUTION
		Self.startDelay = TaskSettings.NO_DELAY
		Self.executionDelay = TaskSettings.NO_DELAY
		Self.checkStartConditionEachTime = False
		Self.expirationDelay = DEFAULT_EXPIRATION_DELAY
	End
	
	Method New(maxNbOfExecution:Int)
		Self.maxNbOfExecution = maxNbOfExecution
		Self.startDelay = TaskSettings.NO_DELAY
		Self.executionDelay = TaskSettings.NO_DELAY
		Self.checkStartConditionEachTime = False
		Self.expirationDelay = DEFAULT_EXPIRATION_DELAY
	End
	
	Method New(maxNbOfExecution:Int, startDelay:Int)
		Self.maxNbOfExecution = maxNbOfExecution
		Self.startDelay = startDelay
		Self.executionDelay = TaskSettings.NO_DELAY
		Self.checkStartConditionEachTime = False
		Self.expirationDelay = DEFAULT_EXPIRATION_DELAY
	End
	
	Method New(maxNbOfExecution:Int, startDelay:Int, executionDelay:Int)
		Self.maxNbOfExecution = maxNbOfExecution
		Self.startDelay = startDelay
		Self.executionDelay = executionDelay
		Self.checkStartConditionEachTime = False
		Self.expirationDelay = DEFAULT_EXPIRATION_DELAY
	End
	
	Method New(maxNbOfExecution:Int, startDelay:Int, executionDelay:Int, checkStartConditionEachTime:Bool)
		Self.maxNbOfExecution = maxNbOfExecution
		Self.startDelay = startDelay
		Self.executionDelay = executionDelay
		Self.checkStartConditionEachTime = checkStartConditionEachTime
		Self.expirationDelay = DEFAULT_EXPIRATION_DELAY
	End
	
	Method New(maxNbOfExecution:Int, startDelay:Int, executionDelay:Int, checkStartConditionEachTime:Bool, expirationDelay:Int)
		Self.maxNbOfExecution = maxNbOfExecution
		Self.startDelay = startDelay
		Self.executionDelay = executionDelay
		Self.checkStartConditionEachTime = checkStartConditionEachTime
		Self.expirationDelay = expirationDelay
	End
	
End

'summary: Représente une tâche.
Class Task

Private

	Field taskId:Int
	Field settings:TaskSettings
	Field nbOfExecution:Int
	Field isFinished:Bool
	Field isStarted:Bool
	Field startedTime:Int
	Field lastExecutionTime:Int
	Field hasErrors:Bool
	Field terminateReason:String
	Field errorCode:Int
	
Public

	'summary: Créer une tâche.
	Method New(taskId:Int, settings:TaskSettings)
		Self.startedTime = Millisecs()
		Self.taskId = taskId
		Self.settings = settings
		Self.isFinished = False
	End
	
	'summary: Obtenir le code d'erreur. (Optionnel)
	Method ErrorCode:Int() Property Final
		Return Self.errorCode
	End
	
	'summary: Déterminer si des erreurs ce sont produites lors de l'éxécution de la tâche.
	Method HasErrors:Bool() Property Final
		Return Self.hasErrors
	End
	
	'summary: Obtenir la raison de la terminaison de la tâche. (Optionnel)
	Method TerminateReason:String() Property Final
		Return Self.terminateReason
	End
	
	'summary: Obtenir l'identifiant de la tâche.
	Method Id:Int() Property Final
		Return Self.taskId
	End
	
	'summary: Obtenir les paramètres de la tâche.
	Method Settings:TaskSettings() Property Final
		Return Self.settings
	End
	
	'summary: Obtenir le temps de démarrage de la tâche.
	Method StartedTime:Int() Property Final
		Return Self.startedTime
	End
	
	'summary: Déterminer si la tâche est démarré.
	Method IsStarted:Int() Property Final
		Return Self.isStarted
	End
	
	'summary: Déterminer si la tâche est toujours active.
	Method IsStillActive:Bool() Property Final
		Return Self.isStarted And Not Self.isFinished
	End
	
	'summary: Déterminer si la tâche est expiré.
	Method HasExpired:Bool() Property Final
		Return (Self.settings.expirationDelay <> TaskSettings.NO_EXPIRATION) And (Self.StartedTime() + (Self.settings.expirationDelay * 1000)) <= Millisecs()
	End
	
	'summary: Obtenir le nombre d'éxécution effectué.
	Method CurrentNbOfExecution:Int() Property Final
		Return Self.nbOfExecution
	End
	
	'summary: Condition à respecter pour démarrer la tâche.
	Method StartCondition:Bool() 
	Print("Super() executed!" + Id())
		Return True
	End
	
	'summary: Condition qui détermine quand la tâche est terminée.
	'IMPORTANT: Il est possible d'utiliser Super.CompleteCondition() dans la méthode correspondante de la classe qui hérite de 'Tasks
	'pour inclure la condition d'un certain nombre maximum d'éxécution possible avant la terminaison de la tâche. 
	'(Si toutefois celle-ci est définie dans la configuration de la tâche)
	Method CompleteCondition:Bool()
		Local endTask:Bool = False
		If Self.settings.maxNbOfExecution <> - 1 Then
			endTask = nbOfExecution >= Self.settings.maxNbOfExecution
		EndIf
		Return endTask
	End
	
	'summary: Condition à respecter pour considéré la tâche comme étant en erreur.
	'IMPORTANT: Il est possible d'utiliser Super.ErrorCondition() dans la méthode correspondante de la classe qui hérite de 'Tasks
	'pour inclure l'expiration d'une tâche comme condition d'erreur. (Si toutefois celle-ci est définie dans la configuration de la tâche)
	Method ErrorCondition:Bool()
		Local endTask:Bool = False
		If Self.settings.expirationDelay <> - 1 Then
			endTask = Self.HasExpired()
		EndIf
		Return endTask Or Self.HasErrors()
	End
	
	'summary: Affiche le rendu associé à la tâche à l'écran.
	Method Render:Void()	
	End
	
	'summary: Méthode éxécuté lorsque la tâche est éxécuté. 
	Method Execute:Void()
	End
	
	'summary: Méthode éxécuté lorsque la tâche est complété.
	Method TaskCompleted:Void()
	End
	
	'summary: Méthode éxécuté lorsque la tâche est en erreur.
	Method TaskError:Void(reason:String, errorCode:Int)
	End
	
	'summary: Considéré la tâche comme terminée avec code d'erreur et raison sans considéré la condition de fin. 
	Method Terminate:Void(hasErrors:Bool, errorCode:Int, reason:String)
		Self.isFinished = True
		Self.hasErrors = hasErrors
		Self.terminateReason = reason
	End
	
	'summary: Considéré la tâche comme terminée  avec code d'erreur sans considéré la condition de fin.
	Method Terminate:Void(hasErrors:Bool, errorCode:Int)
		Self.Terminate(hasErrors, errorCode, "")
	End
	
	'summary: Considéré la tâche comme terminée avec raison sans considéré la condition de fin.
	Method Terminate:Void(hasErrors:Bool, reason:String)
		Self.Terminate(hasErrors, -1, reason)
	End
	
	'summary: Considéré la tâche comme terminée sans considéré la condition de fin.
	Method Terminate:Void()
		Self.Terminate(False, -1, "")
	End

End

'summary: Représente une tâche avec un objet de travail.
Class TaskObject < T > Extends Task
	
Private

	Field workObject:T
	
Public

	'summary: Construire une tâche avec objet de travail.
	Method New(taskId:Int, settings:TaskSettings, workObject:T)
		Super.New(taskId, settings)
		Self.workObject = workObject
	End
	
	'summary: Obtenir l'objet de travail associé à la tâche.
	Method WorkObject:T() Property Final
		Return Self.workObject
	End
	
	'summary: Définir l'objet de travail associé à la tâche.
	Method WorkObject:Void(workObject:T) Property Final
		Self.workObject = workObject
	End

End

'summary: Représente un gestionnaire de groupe de tâches pour gérer plusieurs gestionnaires de tâches.
Class TasksGroupHandler
	
Private

	Field tasksHandlerList:List<TasksHandler>

Public

	'summary: Construire un gestionnaire de groupe de tâches.
	Method New()
		Self.tasksHandlerList = New List<TasksHandler>()
	End
	
	'summary: Enregistrer un gestionnaire de tâches au groupe.
	Method Register:Void(tasksHandler:TasksHandler)
		Self.tasksHandlerList.AddLast(tasksHandler)
	End
	
	'summary: Vider la liste des gestionnaires de tâches.
	Method Clear:Void()
		Self.tasksHandlerList.Clear()
	End
	
	'summary: Terminer toutes les tâches ayant l'identifiant passé en paramètre de toutes les gestionnaires de tâches enregistrés dans le groupe.
	Method TerminateTask:Void(taskId:Int, hasErrors:Bool, errorCode:Int, reason:String)
		For Local th:TasksHandler = EachIn Self.tasksHandlerList
			th.TerminateTask(taskId, hasErrors, errorCode, reason)
		Next
	End
	
	'summary: Mettre à jour l'ensemble des tâches des gestionnaires de tâches.
	Method UpdateTasks:Void()
		For Local th:TasksHandler = EachIn Self.tasksHandlerList
			th.UpdateTasks()
		Next
	End
	
	'summary: Afficher le rendu de l'ensemble des tâches des gestionnaires de tâches.
	Method RenderTasks:Void()
		For Local th:TasksHandler = EachIn Self.tasksHandlerList
			th.RenderTasks()
		Next
	End

End



Rushino(Posted 2013) [#9]
I made a sample but the behavior is not reproductible.

http://sdrv.ms/ZyUr94


marksibly(Posted 2013) [#10]
Can you email me the project?


Rushino(Posted 2013) [#11]
Yes i can. Will do this evening.


Rushino(Posted 2013) [#12]
I have sent you the source code of my project + .js of bug scenario and .js of working scenario depending of if you include tasks to the reflection filter. Thanks a lots for your help! If you have any questions feel free to reply to my email.


Rushino(Posted 2013) [#13]
I sent you an update by mail. Seem to have found the problem. However that still strange..