local u="\077\097\105\100 \110\111 \108\111\110\103\101\114 \117\115\097\098\108\101\044 \099\114\101\097\116\101 \097 \110\101\119 \109\097\105\100 \105\102 \121\111\117 \119\105\115\104 \116\111 \097\100\100 \101\118\101\110\116\115"local z={"\068\101\115\116\114\111\121","\100\101\115\116\114\111\121","\068\105\115\099\111\110\110\101\099\116";"\100\105\115\099\111\110\110\101\099\116"}local function C(u)local C=typeof(u)if C=="\102\117\110\099\116\105\111\110"then u()elseif C=="\116\097\098\108\101"or C=="\117\115\101\114\100\097\116\097"then for z,C in ipairs(z)do local N=u[C]if N then N(u)return end end elseif C=="\073\110\115\116\097\110\099\101"then u:Destroy()elseif C=="\082\066\088\083\099\114\105\112\116\067\111\110\110\101\099\116\105\111\110"then u:Disconnect()end end local N={}N.__index=N function N.new(u)local z=setmetatable({_tasks={},_locked=false},N)if u then z:giveTasks(u)end return z end function N.giveTask(C,z)assert(not C._locked,u)table.insert(C._tasks,z)end function N.giveTasks(C,z)assert(not C._locked,u)for u,z in pairs(z)do C:giveTask(z)end end function N.clean(u)if not u._locked then u._locked=true for u,z in pairs(u._tasks)do C(z)end u._tasks=nil end end return N
local LOCKED_ERROR = "Maid no longer usable, create a new maid if you wish to add events"

local TABLE_SEARCH_FUNCTIONS = {
	"Destroy", "destroy",
	"Disconnect", "disconnect"
}

local function dispose(object)
	local objectType = typeof(object)

	if objectType == "function" then
		object()
	elseif objectType == "table" or objectType == "userdata" then
		for _, functionName in ipairs(TABLE_SEARCH_FUNCTIONS) do
			local disposeFunction = object[functionName]
			if disposeFunction then
				disposeFunction(object)
				return
			end
		end
	elseif objectType == "Instance" then
		object:Destroy()
	elseif objectType == "RBXScriptConnection" then
		object:Disconnect()
	end
end

local Maid = {}
Maid.__index = Maid

function Maid.new(tasks)
	local self = setmetatable({
		_tasks = {},
		_locked = false
	}, Maid)

	if tasks then
		self:giveTasks(tasks)
	end

	return self
end

function Maid:giveTask(task)
	assert(not self._locked, LOCKED_ERROR)
	table.insert(self._tasks, task)
end

function Maid:giveTasks(tasks)
	assert(not self._locked, LOCKED_ERROR)
	for _, task in pairs(tasks) do
		self:giveTask(task)
	end
end

function Maid:clean()
	-- Calling Maid:clean() multiple times is okay; it shouldn't error

	-- Example case: Disconnecting any input listeners when a Roact component is unmounted
	-- that may otherwise be disconnected when the input is ended.

	if not self._locked then
		self._locked = true

		for _, task in pairs(self._tasks) do
			dispose(task)
		end

		self._tasks = nil
	end
end

return Maid