///|
priv enum CallbackFreeBindingSnapshot {
CallbackFreeBindingMissing
CallbackFreeBindingPresent(Value)
CallbackFreeBindingUnsafe
}
///|
fn callback_free_binding_value_is_unsafe(value : Value) -> Bool {
match value {
Object(data) =>
data.class_name == MODULE_NAMESPACE_CACHE_CLASS ||
data.class_name == "ModuleTDZ" ||
data.class_name == "ModuleExportCell"
_ => false
}
}
///|
fn callback_free_binding_snapshot(
env : Environment,
name : String,
) -> CallbackFreeBindingSnapshot {
guard env.with_object is None else { return CallbackFreeBindingUnsafe }
match env.bindings.get(name) {
None => CallbackFreeBindingMissing
Some(binding) if !binding.initialized => CallbackFreeBindingUnsafe
Some(binding) if callback_free_binding_value_is_unsafe(binding.value) =>
CallbackFreeBindingUnsafe
Some(binding) => CallbackFreeBindingPresent(binding.value)
}
}
///|
fn callback_free_binding_in_plain_chain(
env : Environment,
name : String,
) -> CallbackFreeBindingSnapshot {
let mut current : Environment? = Some(env)
while true {
match current {
None => return CallbackFreeBindingMissing
Some(candidate) =>
match callback_free_binding_snapshot(candidate, name) {
CallbackFreeBindingMissing => current = candidate.parent
CallbackFreeBindingPresent(value) =>
return CallbackFreeBindingPresent(value)
CallbackFreeBindingUnsafe => return CallbackFreeBindingUnsafe
}
}
}
CallbackFreeBindingMissing
}