'From Squeak5.3alpha of 6 December 2019 [latest update: #19256] on 30 December 2019 at 8:24:53 pm'!

!Context methodsFor: 'private' stamp: 'ct 12/30/2019 20:23'!
privSwapSender: coroutine 

	| oldSender |
	oldSender := sender.
	sender := coroutine.
	^oldSender! !

!Context methodsFor: 'controlling' stamp: 'ct 12/30/2019 20:23'!
swapSender: coroutine 
	"Replace the receiver's sender with coroutine and answer the receiver's previous sender."

	| ctxt prevCtxt result essentialSenders essentialHome |
	essentialSenders := OrderedCollection new.
	ctxt := self.
	[prevCtxt := ctxt.
	(ctxt := ctxt sender) notNil and: [
		essentialSenders notEmpty ==> [ctxt isEssential]]]
			whileTrue: [
				ctxt isEssential ifTrue: [
					essentialSenders add: ctxt.
					prevCtxt privSender: ctxt sender.
					ctxt := prevCtxt]].
	
	result := self privSwapSender: coroutine.
	
	(essentialSenders isEmpty or: [essentialSenders last = coroutine])
		ifFalse: [
			essentialHome := essentialSenders last sender.
			ctxt := coroutine.
			[essentialHome = ctxt or: [essentialHome notNil and: [essentialHome hasSender: ctxt]]]
				whileFalse: [ctxt := ctxt sender ifNil: [thisContext return]].
			essentialSenders last privSender: nil.
			ctxt insertSender: essentialSenders first].
	
	^ result! !

!Context methodsFor: 'debugger access' stamp: 'ct 12/28/2019 20:02'!
isEssential

	^ self receiver isBlock
		and: [#(on:do: ensure:) includes: self selector]
		and: [self arguments anySatisfy: [:arg |
			arg isBlock and: [
				arg method selector = #runUntilErrorOrReturnFrom:]]]! !

