Get the stack position of an handler

If you run the script below in Script Debugger, you can see on the right side the list of “stacked” handers at any momento of the script, which is very convenient for positioning a line of code during the running when in a long script.

I wonder if it is possible to “extract” this information from within the script with a command such as getMyStackList.

Thanks!!!

 on run
	handler1("Luciano") --> Stak: 1.Run 
end run


on handler1(someText)
	display notification someText -->  Stak: 1. Run; 2. handler1
	set moreText to someText & " from handler1"
	handler2(moreText)
end handler1

on handler2(moreText)
	display notification moreText -->  Stak: 1. Run; 2. handler1; 3. handler2
	set evenmoreText to moreText & " and from handler2"
	handler3(evenmoreText)
end handler2

on handler3(evenmoreText)
	display notification evenmoreText -- Stak: 1. Run; 2. handler1; 3. handler2; 4. handler3
	set evenevenmoreText to evenmoreText & " from handler3"
	getMyStackList --???? Is this possible ??
end handler3

Alas, no.

Can I ask you how (just the concept behind how) SD traces the stack list?
Trace the steps down it is quite simple, I cannot see an obvious way to trace the return steps.
If you cannot answer - since it might be a legally protected information - I completely understand that.
Thanks anyway !

I think, using global variable, you can trace were the script is each moment. Run following script and stop at different moments, to see were it is. Maybe, I don’t understand the question correctly:


global trace

on run
	set trace to {"1. Run"}
	delay 1
	handler1()
	delay 1
	set end of trace to "1. Run"
end run


on handler1()
	delay 1
	set end of trace to "2. handler1"
	handler2()
	delay 1
	set end of trace to "2. handler1"
end handler1

on handler2()
	delay 1
	set end of trace to "3. handler2"
	handler3()
	delay 1
	set end of trace to "3. handler2"
end handler2

on handler3()
	delay 1
	set end of trace to "4. handler3"
end handler3

Basically it injects a whole lot of instrumentation code and interposes its own OSA component.

I updated my test to more correct. The delays is not required. They are only for testing purposes. To give you more time to stop the script at any execution point. You can remove all of them in the real-life script.

Thanks to both.
@Robert:

I was thinking along the same line, with this script (which is based on your input), which now populates and de-populates the global ‘trace’:

global trace

on run
	set handlerName to "Run"
	set trace to {handlerName}
	delay 0.2
	handler1()
	delay 0.2
	checkHandlerList(trace, handlerName)
end run


on handler1()
	set handlerName to "handler1"
	checkHandlerList(trace, handlerName)
	
	handler2()
	
	delay 0.2
	checkHandlerList(trace, handlerName)
end handler1

on handler2()
	set handlerName to "handler2"
	delay 0.2
	checkHandlerList(trace, handlerName)
	
	handler3()
	delay 0.2
	
	checkHandlerList(trace, handlerName)
end handler2

on handler3()
	set handlerName to "handler3"
	delay 0.2
	checkHandlerList(trace, handlerName)
	
	beep
	
	delay 0.2
	checkHandlerList(trace, handlerName)
end handler3


on checkHandlerList(thelist, theHandlerName)
	{thelist, theHandlerName}
	if last item of thelist is theHandlerName then
		set thelist to reverse of (rest of (reverse of thelist))
	else
		set end of thelist to theHandlerName
	end if
	set trace to thelist
end checkHandlerList

To make this approach more useful for debugging errors, you can use script-wide try block. To get trace when error occurs. For example, this way:


global trace

on run
	try -- script-wide try block
		set trace to {"1. Run"}
		delay 1
		handler1()
		delay 1
		set end of trace to "1. Run"
	on error
		return trace
	end try
end run

on handler1()
	delay 1
	set end of trace to "2. handler1"
	handler2() -- error occurs here (handler2 is absent)
	delay 1
	set end of trace to "2. handler1"
end handler1