How do events/signals work under the hood?

So one thing I cannot really find lots of info about is how exactly events and signals work.
I cannot find any details about how they’re garbage collected and under what conditions.

And since the deferred events update events work slightly different if you have your game set to deferred so this also requires a slight change to how some scripts clean up things after object destruction.

One of the things I’m concerned about in Roblox is not knowing what the exact conditions are for events to be disconnected and worries about floating event connections.

I think we all know that…

-- Inside a BasePart.

script.Parent.Touched:Connect(function(object)
 print("Touched: " .. object:GetFullName())
end)

If the BasePart were to be :Destroy()'d, all events get disconnected, so it’s safe to assume that this will be garbage collected properly and securely.

Now onto a slightly more complex case.

Let’s say that in workspace.Zombie.AIScript we have the following:

local targets = {}

...

function addTarget(object)

 if not object:FindFirstChild("Humanoid") then return end

 table.insert(targets, object)

end

local event = workspace.ChildAdded:Connect(addTarget)

Here we have a script inside a zombie that tracks targets.

Zombie later gets killed in the game and is :Destroy()'d.

What happens to this event?
The zombie is destroyed, but we’re listening to an event of game.Workspace.

And we all know that workspace never gets :Destroy()'d (as that would basically delete/break the game if you could), so it’s connections will never be broken by game logic.

What happens to the event we connected in the script?

Module script.

Now let’s take the above example but now we apply it using module scripts for modular zombie AI.

game.ReplicatedStorage.Modules.ZombieAI

local zombie_class = {}
zombie_class.__index = zombie

function zombie_class:new(model)
 local zombie = setmetatable({}, self)

 zombie.model = model
 zombie.targets = {}

 ...

 model.Humanoid.Died:Connect(function() -- Gets GC'd when model is Destroy()'d.
  zombie:die()
 end)

 workspace.ChildAdded:Connect(function(target) -- ???
  if not target:FindFirstChild("Humanoid") then return end

  table.insert(zombie.targets, target)
 end)
 
 ...

 return zombie
end


In workspace.Zombie.AIScript:

local zombie_module = require(game.ReplicatedStorage.Modules.ZombieAI)

local zombie = zombie_module:new(script.Parent)

In this case I don’t know if the event gets properly disposed of because it’s created inside a module script.

The script that initiated it will be :Destroy()'d when the zombie dies, however module scripts can technically still execute their code even if the script that initiated it got deleted???

And what would happen if I did this same thing, but inside an Actor instead?

As far as I know, every Actor creates it’s own Luau Virtual Machine for Parallel Luau and I assume that virtual machine is also deleted/cleansed whenever the Actor is :Destroy()'d.

But still have no idea what happens with events and signal connections that are made with an Actor and I can find no documentation or other posts about it.