Open tagomoris opened 3 years ago
The method to register error handlers: https://github.com/sinatra/sinatra/blob/v2.1.0/lib/sinatra/base.rb#L1310-L1316
def error(*codes, &block)
args = compile! "ERROR", /.*/, block
codes = codes.flat_map(&method(:Array))
codes << Exception if codes.empty?
codes << Sinatra::NotFound if codes.include?(404)
codes.each { |c| (@errors[c] ||= []) << args }
end
The compiler of handlers: https://github.com/sinatra/sinatra/blob/v2.1.0/lib/sinatra/base.rb#L1661
def compile!(verb, path, block, **options)
# Because of self.options.host
host_name(options.delete(:host)) if options.key?(:host)
# Pass Mustermann opts to compile()
route_mustermann_opts = options.key?(:mustermann_opts) ? options.delete(:mustermann_opts) : {}.freeze
options.each_pair { |option, args| send(option, *args) }
pattern = compile(path, route_mustermann_opts)
method_name = "#{verb} #{path}"
unbound_method = generate_method(method_name, &block)
conditions, @conditions = @conditions, []
wrapper = block.arity != 0 ?
proc { |a, p| unbound_method.bind(a).call(*p) } :
proc { |a, p| unbound_method.bind(a).call }
[ pattern, conditions, wrapper ]
end
Because all routes/filters/middlewares/extensions/errors(error handlers) are stored as class instance variable. And those values are sometimes Proc objects or unbound methods dynamically created with contexts. We need to rewrite Sinatra entirely if we want to run it on Ractor.