'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:]]]! !