function Promise._all(n,t,H)if type(t)~="\116\097\098\108\101"then error(string.format(ERROR_NON_LIST,"\080\114\111\109\105\115\101\046\097\108\108"),3)end for n,t in pairs(t)do if not Promise.is(t)then error(string.format(ERROR_NON_PROMISE_IN_LIST,"\080\114\111\109\105\115\101\046\097\108\108",tostring(n)),3)end end if#t==0 or H==0 then return Promise.resolve({})end return Promise._new(n,function(n,B,S)local Z={}local I={}local O=0 local G=0 local i=false local function o()for n,t in ipairs(I)do t:cancel()end end local function k(B,...)if i then return end O=O+1 if H==nil then Z[B]=...else Z[O]=...end if O>=(H or#t)then i=true n(Z)o()end end S(o)for n,S in ipairs(t)do I[n]=S:andThen(function(...)k(n,...)end,function(...)G=G+1 if H==nil or#t-G<H then o()i=true B(...)end end)end if i then o()end end)end

function Promise._all(traceback, promises, amount)
	if type(promises) ~= "table" then
		error(string.format(ERROR_NON_LIST, "Promise.all"), 3)
	end

	-- We need to check that each value is a promise here so that we can produce
	-- a proper error rather than a rejected promise with our error.
	for i, promise in pairs(promises) do
		if not Promise.is(promise) then
			error(string.format(ERROR_NON_PROMISE_IN_LIST, "Promise.all", tostring(i)), 3)
		end
	end

	-- If there are no values then return an already resolved promise.
	if #promises == 0 or amount == 0 then
		return Promise.resolve({})
	end

	return Promise._new(traceback, function(resolve, reject, onCancel)
		-- An array to contain our resolved values from the given promises.
		local resolvedValues = {}
		local newPromises = {}

		-- Keep a count of resolved promises because just checking the resolved
		-- values length wouldn't account for promises that resolve with nil.
		local resolvedCount = 0
		local rejectedCount = 0
		local done = false

		local function cancel()
			for _, promise in ipairs(newPromises) do
				promise:cancel()
			end
		end

		-- Called when a single value is resolved and resolves if all are done.
		local function resolveOne(i, ...)
			if done then
				return
			end

			resolvedCount = resolvedCount + 1

			if amount == nil then
				resolvedValues[i] = ...
			else
				resolvedValues[resolvedCount] = ...
			end

			if resolvedCount >= (amount or #promises) then
				done = true
				resolve(resolvedValues)
				cancel()
			end
		end

		onCancel(cancel)

		-- We can assume the values inside `promises` are all promises since we
		-- checked above.
		for i, promise in ipairs(promises) do
			newPromises[i] = promise:andThen(function(...)
				resolveOne(i, ...)
			end, function(...)
				rejectedCount = rejectedCount + 1

				if amount == nil or #promises - rejectedCount < amount then
					cancel()
					done = true

					reject(...)
				end
			end)
		end

		if done then
			cancel()
		end
	end)
end
