1# frozen_string_literal: true
 2
 3require "em_promise"
 4
 5module Rack
 6	class Fiber
 7		def initialize(app)
 8			@app = app
 9		end
10
11		def call(env)
12			async_callback = env.delete("async.callback")
13			run_fiber(env, async_callback)
14			throw :async
15		end
16
17	protected
18
19		def run_fiber(env, async_callback)
20			# Use EMPromise to get a Fiber trampoline that can be shared by
21			# other EMPromise down the stack. Also works as a normal Fiber if
22			# no one uses EMPromise.
23			EMPromise.resolve(nil).then {
24				async_callback.call(@app.call(env))
25			}.catch { |e|
26				async_callback.call([500, {}, [e.to_s]])
27			}
28		end
29	end
30end