function Promise.new(n,T)if T~=nil and not Promise.is(T)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 Y={_source=debug.traceback(),[PromiseMarker]=true;_status=Promise.Status.Started;_values=nil,_valuesLength=-1;_unhandledRejection=true,_queuedResolve={},_queuedReject={},_queuedFinally={},_cancellationHook=nil;_parent=T;_consumers=setmetatable({},{__mode="\107"})}if T and T._status==Promise.Status.Started then T._consumers[Y]=true end setmetatable(Y,Promise)local function F(...)Y:_resolve(...)end local function v(...)Y:_reject(...)end local function G(n)if n then if Y._status==Promise.Status.Cancelled then n()else Y._cancellationHook=n end end return Y._status==Promise.Status.Cancelled end local g,j=wpcallPacked(n,F,v,G)local u=j[1]local U=j[2]if not u and Y._status==Promise.Status.Started then v(U)end return Y end

function Promise.new(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 = debug.traceback(),

		-- A tag to identify us as a promise
		[PromiseMarker] = true,

		_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.
		_parent = parent,

		_consumers = setmetatable({}, {
			__mode = "k";
		}),
	}

	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

	local _, result = wpcallPacked(callback, resolve, reject, onCancel)
	local ok = result[1]
	local err = result[2]

	if not ok and self._status == Promise.Status.Started then
		reject(err)
	end

	return self
end
