function AttributeUtils.promiseAttribute(G,v,d,l)assert(typeof(G)=="\073\110\115\116\097\110\099\101","\066\097\100 \105\110\115\116\097\110\099\101")assert(type(v)=="\115\116\114\105\110\103","\066\097\100 \097\116\116\114\105\098\117\116\101\078\097\109\101")assert(CancelToken.isCancelToken(l)or l==nil,"\066\097\100 \099\097\110\099\101\108\084\111\107\101\110")d=d or DEFAULT_PREDICATE do local l=G:GetAttribute(v)if d(l)then return Promise.resolved(l)end end local C=Promise.new()local N=Maid.new()N:GiveTask(C)if l then N:GiveTask(l.Cancelled:Connect(function()C:Reject()end))end N:GiveTask((G:GetAttributeChangedSignal(v)):Connect(function()local l=G:GetAttribute(v)if d(l)then C:Resolve(l)end end))C:Finally(function()N:DoCleaning()end)return C end

function AttributeUtils.promiseAttribute(instance, attributeName, predicate, cancelToken)
	assert(typeof(instance) == "Instance", "Bad instance")
	assert(type(attributeName) == "string", "Bad attributeName")
	assert(CancelToken.isCancelToken(cancelToken) or cancelToken == nil, "Bad cancelToken")

	predicate = predicate or DEFAULT_PREDICATE

	do
		local attributeValue = instance:GetAttribute(attributeName)
		if predicate(attributeValue) then
			return Promise.resolved(attributeValue)
		end
	end

	local promise = Promise.new()
	local maid = Maid.new()
	maid:GiveTask(promise)

	if cancelToken then
		maid:GiveTask(cancelToken.Cancelled:Connect(function()
			promise:Reject()
		end))
	end

	maid:GiveTask(instance:GetAttributeChangedSignal(attributeName):Connect(function()
		local attributeValue = instance:GetAttribute(attributeName)
		if predicate(attributeValue) then
			promise:Resolve(attributeValue)
		end
	end))

	promise:Finally(function()
		maid:DoCleaning()
	end)

	return promise
end

