function Promise._executeThen(U,V,L,B)if U._fulfilled then if type(V)=="\102\117\110\099\116\105\111\110"then if B then B:Resolve(V(unpack(U._fulfilled,1,U._valuesLength)))return B else local L=table.pack(V(unpack(U._fulfilled,1,U._valuesLength)))if L.n==0 then return _emptyFulfilledPromise elseif L.n==1 and Promise.isPromise(L[1])then return L[1]else local V=Promise.new()V:Resolve(table.unpack(L,1,L.n))return V end end else if B then B:_fulfill(U._fulfilled,U._valuesLength)return B else return U end end elseif U._rejected then if type(L)=="\102\117\110\099\116\105\111\110"then if B then B:Resolve(L(unpack(U._rejected,1,U._valuesLength)))return B else local V=table.pack(L(unpack(U._rejected,1,U._valuesLength)))if V.n==0 then return _emptyFulfilledPromise elseif V.n==1 and Promise.isPromise(V[1])then return V[1]else local L=Promise.new()L:Resolve(table.unpack(V,1,V.n))return L end end else if B then B:_reject(U._rejected,U._valuesLength)return B else return U end end else error("\073\110\116\101\114\110\097\108 \101\114\114\111\114\058 \115\116\105\108\108 \112\101\110\100\105\110\103")end end
--[=[
	@private

	@param onFulfilled function?
	@param onRejected function?
	@param promise2 Promise<T>? -- May be nil. If it is, then we have the option to return self
	@return Promise
]=]
function Promise:_executeThen(onFulfilled, onRejected, promise2)
	if self._fulfilled then
		if type(onFulfilled) == "function" then
			-- If either onFulfilled or onRejected returns a value x, run
			-- the Promise Resolution Procedure [[Resolve]](promise2, x).
			if promise2 then
				promise2:Resolve(onFulfilled(unpack(self._fulfilled, 1, self._valuesLength)))
				return promise2
			else
				local results = table.pack(onFulfilled(unpack(self._fulfilled, 1, self._valuesLength)))
				if results.n == 0 then
					return _emptyFulfilledPromise
				elseif results.n == 1 and Promise.isPromise(results[1]) then
					return results[1]
				else
					local promise = Promise.new()
					-- Technically undefined behavior from A+, but we'll resolve to nil like ES6 promises
					promise:Resolve(table.unpack(results, 1, results.n))
					return promise
				end
			end
		else
			-- If onFulfilled is not a function, it must be ignored.
			-- If onFulfilled is not a function and promise1 is fulfilled,
			-- promise2 must be fulfilled with the same value as promise1.
			if promise2 then
				promise2:_fulfill(self._fulfilled, self._valuesLength)
				return promise2
			else
				return self
			end
		end
	elseif self._rejected then
		if type(onRejected) == "function" then
			-- If either onFulfilled or onRejected returns a value x, run
			-- the Promise Resolution Procedure [[Resolve]](promise2, x).
			if promise2 then
				promise2:Resolve(onRejected(unpack(self._rejected, 1, self._valuesLength)))
				return promise2
			else
				local results = table.pack(onRejected(unpack(self._rejected, 1, self._valuesLength)))
				if results.n == 0 then
					return _emptyFulfilledPromise
				elseif results.n == 1 and Promise.isPromise(results[1]) then
					return results[1]
				else
					local promise = Promise.new()
					-- Technically undefined behavior from A+, but we'll resolve to nil like ES6 promises
					promise:Resolve(table.unpack(results, 1, results.n))
					return promise
				end
			end
		else
			-- If onRejected is not a function, it must be ignored.
			-- If onRejected is not a function and promise1 is rejected, promise2 must be
			-- rejected with the same reason as promise1.
			if promise2 then
				promise2:_reject(self._rejected, self._valuesLength)

				return promise2
			else
				return self
			end
		end
	else
		error("Internal error: still pending")
	end
end
