local I={Error=Error;Status=makeEnum("\080\114\111\109\105\115\101\046\083\116\097\116\117\115",{"\083\116\097\114\116\101\100";"\082\101\115\111\108\118\101\100";"\082\101\106\101\099\116\101\100";"\067\097\110\099\101\108\108\101\100"}),_getTime=os.clock,_timeEvent=(game:GetService("\082\117\110\083\101\114\118\105\099\101")).Heartbeat}I.prototype={}I.__index=I.prototype function I._new(b,V,p)if p~=nil and not I.is(p)then error("\065\114\103\117\109\101\110\116 \035\050 \116\111 \080\114\111\109\105\115\101\046\110\101\119 \109\117\115\116 \098\101 \097 \112\114\111\109\105\115\101 \111\114 \110\105\108",2)end local h={_source=b;_status=I.Status.Started,_values=nil,_valuesLength=-1;_unhandledRejection=true;_queuedResolve={},_queuedReject={},_queuedFinally={},_cancellationHook=nil;_parent=p;_consumers=setmetatable({},MODE_KEY_METATABLE)}if p and p._status==I.Status.Started then p._consumers[h]=true end setmetatable(h,I)local function t(...)h:_resolve(...)end local function i(...)h:_reject(...)end local function Z(b)if b then if h._status==I.Status.Cancelled then b()else h._cancellationHook=b end end return h._status==I.Status.Cancelled end;(coroutine.wrap(function()local I,b,p=runExecutor(h._source,V,t,i,Z)if not I then i(p[1])end end))()return h end
--[=[
	An enum value used to represent the Promise's status.
	@interface Status
	@tag enum
	@within Promise
	.Started "Started" -- The Promise is executing, and not settled yet.
	.Resolved "Resolved" -- The Promise finished successfully.
	.Rejected "Rejected" -- The Promise was rejected.
	.Cancelled "Cancelled" -- The Promise was cancelled before it finished.
]=]
--[=[
	@prop Status Status
	@within Promise
	@readonly
	@tag enums
	A table containing all members of the `Status` enum, e.g., `Promise.Status.Resolved`.
]=]
--[=[
	A Promise is an object that represents a value that will exist in the future, but doesn't right now.
	Promises allow you to then attach callbacks that can run once the value becomes available (known as *resolving*),
	or if an error has occurred (known as *rejecting*).

	@class Promise
	@__index prototype
]=]
local Promise = {
	Error = Error,
	Status = makeEnum("Promise.Status", { "Started", "Resolved", "Rejected", "Cancelled" }),
	_getTime = os.clock,
	_timeEvent = game:GetService("RunService").Heartbeat,
}
Promise.prototype = {}
Promise.__index = Promise.prototype

function Promise._new(traceback, callback, parent)
	if parent ~= nil and not Promise.is(parent) then
		error("Argument #2 to Promise.new must be a promise or nil", 2)
	end

	local self = {
		-- Used to locate where a promise was created
		_source = traceback,

		_status = Promise.Status.Started,

		-- A table containing a list of all results, whether success or failure.
		-- Only valid if _status is set to something besides Started
		_values = nil,

		-- Lua doesn't like sparse arrays very much, so we explicitly store the
		-- length of _values to handle middle nils.
		_valuesLength = -1,

		-- Tracks if this Promise has no error observers..
		_unhandledRejection = true,

		-- Queues representing functions we should invoke when we update!
		_queuedResolve = {},
		_queuedReject = {},
		_queuedFinally = {},

		-- The function to run when/if this promise is cancelled.
		_cancellationHook = nil,

		-- The "parent" of this promise in a promise chain. Required for
		-- cancellation propagation upstream.
		_parent = parent,

		-- Consumers are Promises that have chained onto this one.
		-- We track them for cancellation propagation downstream.
		_consumers = setmetatable({}, MODE_KEY_METATABLE),
	}

	if parent and parent._status == Promise.Status.Started then
		parent._consumers[self] = true
	end

	setmetatable(self, Promise)

	local function resolve(...)
		self:_resolve(...)
	end

	local function reject(...)
		self:_reject(...)
	end

	local function onCancel(cancellationHook)
		if cancellationHook then
			if self._status == Promise.Status.Cancelled then
				cancellationHook()
			else
				self._cancellationHook = cancellationHook
			end
		end

		return self._status == Promise.Status.Cancelled
	end

	coroutine.wrap(function()
		local ok, _, result = runExecutor(self._source, callback, resolve, reject, onCancel)

		if not ok then
			reject(result[1])
		end
	end)()

	return self
end
