def env_capture(&blk)
blk
end
def env_closed_proc
local = :held
env_capture { [local, __env_svar_read] }
end
def env_closed_writer(v)
local = :held
env_capture { __env_svar_write(v); __env_svar_read }
end
def env_owner_before_escape(v)
local = :held
__env_svar_write(v)
env_capture { [local, __env_svar_read] }
end
def env_closed_pair
local = :held
[env_capture { __env_svar_write("shared") }, env_capture { __env_svar_read }]
end
assert('REnv, closed env carries no slot until a scope needs one') do
pr = env_closed_proc
assert_false __env_svar?(pr)
assert_equal :none, __env_svar_slot(pr)
GC.start
assert_equal [:held, nil], pr.call
end
assert('REnv, a live write closes with the slot already made') do
pr = env_owner_before_escape("owned")
assert_true __env_svar?(pr)
assert_equal :svar, __env_svar_slot(pr)
GC.start
assert_equal [:held, "owned"], pr.call
assert_equal :svar, __env_svar_slot(pr)
end
assert('REnv, C closure env carries no slot') do
pr = __env_cfunc_proc("cfunc")
assert_false __env_svar?(pr)
assert_equal :none, __env_svar_slot(pr)
GC.start
assert_equal "cfunc", pr.call
end
assert('REnv, reading special variables leaves a slotless env alone') do
pr = env_closed_proc
assert_equal [:held, nil], pr.call
assert_false __env_svar?(pr)
assert_equal :none, __env_svar_slot(pr)
end
assert('REnv, the first write grows a slotless env into the slot') do
pr = env_closed_writer("written")
len = __env_len(pr)
assert_false __env_svar?(pr)
assert_equal "written", pr.call
assert_true __env_svar?(pr)
assert_equal :svar, __env_svar_slot(pr)
assert_equal len, __env_len(pr)
assert_equal "written", pr.call
GC.start
assert_equal "written", pr.call
assert_equal :svar, __env_svar_slot(pr)
end
assert('REnv, a grown env is the one scope both its procs see') do
writer, reader = env_closed_pair
assert_false __env_svar?(writer)
assert_false __env_svar?(reader)
writer.call
assert_true __env_svar?(reader)
GC.start
assert_equal "shared", reader.call
end
assert('REnv, the shutdown detach keeps the top-level container') do
kept = __env_shutdown_svar
skip 'the teardown window opens under MRB_GC_STRESS with a compiler' if kept.nil?
assert_true kept
end
assert('REnv, MRB_ENV_SET_BIDX() evaluates its index exactly once') do
assert_equal 1, __env_set_bidx_eval_count
end