| 
									
										
										
										
											2024-08-12 10:30:59 +01:00
										 |  |  | # typed: true # rubocop:todo Sorbet/StrictSigil | 
					
						
							| 
									
										
										
										
											2021-04-13 17:39:59 +01:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require "warnings" | 
					
						
							|  |  |  | Warnings.ignore(/warning: callcc is obsolete; use Fiber instead/) do | 
					
						
							|  |  |  |   require "continuation" | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Provides the ability to optionally ignore errors raised and continue execution. | 
					
						
							|  |  |  | module Ignorable | 
					
						
							|  |  |  |   # Marks exceptions which can be ignored and provides | 
					
						
							|  |  |  |   # the ability to jump back to where it was raised. | 
					
						
							|  |  |  |   module ExceptionMixin | 
					
						
							|  |  |  |     attr_accessor :continuation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def ignore | 
					
						
							|  |  |  |       continuation.call | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def self.hook_raise | 
					
						
							| 
									
										
										
										
											2025-07-14 14:48:08 +01:00
										 |  |  |     # TODO: migrate away from this inline class here, they don't play nicely with | 
					
						
							|  |  |  |     # Sorbet, when we migrate to `typed: strict` | 
					
						
							|  |  |  |     # rubocop:todo Sorbet/BlockMethodDefinition | 
					
						
							| 
									
										
										
										
											2021-04-13 17:39:59 +01:00
										 |  |  |     Object.class_eval do | 
					
						
							|  |  |  |       alias_method :original_raise, :raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def raise(*) | 
					
						
							|  |  |  |         callcc do |continuation| | 
					
						
							|  |  |  |           super | 
					
						
							| 
									
										
										
										
											2025-01-12 16:56:48 +00:00
										 |  |  |         # Handle all possible exceptions. | 
					
						
							| 
									
										
										
										
											2021-04-13 17:39:59 +01:00
										 |  |  |         rescue Exception => e # rubocop:disable Lint/RescueException | 
					
						
							|  |  |  |           unless e.is_a?(ScriptError) | 
					
						
							|  |  |  |             e.extend(ExceptionMixin) | 
					
						
							| 
									
										
										
										
											2023-03-31 08:34:33 -07:00
										 |  |  |             T.cast(e, ExceptionMixin).continuation = continuation | 
					
						
							| 
									
										
										
										
											2021-04-13 17:39:59 +01:00
										 |  |  |           end | 
					
						
							|  |  |  |           super(e) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       alias_method :fail, :raise | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2025-07-14 14:48:08 +01:00
										 |  |  |     # rubocop:enable Sorbet/BlockMethodDefinition | 
					
						
							| 
									
										
										
										
											2021-04-13 17:39:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return unless block_given? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     yield | 
					
						
							|  |  |  |     unhook_raise | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def self.unhook_raise | 
					
						
							|  |  |  |     Object.class_eval do | 
					
						
							|  |  |  |       alias_method :raise, :original_raise | 
					
						
							|  |  |  |       alias_method :fail, :original_raise | 
					
						
							|  |  |  |       undef :original_raise | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |