local g do g={Kind=makeEnum("\080\114\111\109\105\115\101\046\069\114\114\111\114\046\075\105\110\100",{"\069\120\101\099\117\116\105\111\110\069\114\114\111\114";"\065\108\114\101\097\100\121\067\097\110\099\101\108\108\101\100","\078\111\116\082\101\115\111\108\118\101\100\073\110\084\105\109\101";"\084\105\109\101\100\079\117\116"})}g.__index=g function g.new(S,K)S=S or{}return setmetatable({error=tostring(S.error)or"\091\084\104\105\115 \101\114\114\111\114 \104\097\115 \110\111 \101\114\114\111\114 \116\101\120\116\046\093",trace=S.trace;context=S.context,kind=S.kind;parent=K;createdTick=os.clock();createdTrace=debug.traceback()},g)end function g.is(g)if type(g)=="\116\097\098\108\101"then local S=getmetatable(g)if type(S)=="\116\097\098\108\101"then return rawget(g,"\101\114\114\111\114")~=nil and type(rawget(S,"\101\120\116\101\110\100"))=="\102\117\110\099\116\105\111\110"end end return false end function g.isKind(S,K)assert(K~=nil,"\065\114\103\117\109\101\110\116 \035\050 \116\111 \080\114\111\109\105\115\101\046\069\114\114\111\114\046\105\115\075\105\110\100 \109\117\115\116 \110\111\116 \098\101 \110\105\108")return g.is(S)and S.kind==K end function g.extend(K,S)S=S or{}S.kind=S.kind or K.kind return g.new(S,K)end function g.getErrorChain(g)local S={g}while S[#S].parent do table.insert(S,S[#S].parent)end return S end function g.__tostring(g)local S={string.format("-- \080\114\111\109\105\115\101\046\069\114\114\111\114\040\037\115\041 --",g.kind or"\063")}for g,K in ipairs(g:getErrorChain())do table.insert(S,table.concat({K.trace or K.error,K.context},"\n"))end return table.concat(S,"\n")end end

local Error do
	Error = {
		Kind = makeEnum("Promise.Error.Kind", {
			"ExecutionError",
			"AlreadyCancelled",
			"NotResolvedInTime",
			"TimedOut",
		}),
	}
	Error.__index = Error

	function Error.new(options, parent)
		options = options or {}
		return setmetatable({
			error = tostring(options.error) or "[This error has no error text.]",
			trace = options.trace,
			context = options.context,
			kind = options.kind,
			parent = parent,
			createdTick = os.clock(),
			createdTrace = debug.traceback(),
		}, Error)
	end

	function Error.is(anything)
		if type(anything) == "table" then
			local metatable = getmetatable(anything)

			if type(metatable) == "table" then
				return rawget(anything, "error") ~= nil and type(rawget(metatable, "extend")) == "function"
			end
		end

		return false
	end

	function Error.isKind(anything, kind)
		assert(kind ~= nil, "Argument #2 to Promise.Error.isKind must not be nil")

		return Error.is(anything) and anything.kind == kind
	end

	function Error:extend(options)
		options = options or {}

		options.kind = options.kind or self.kind

		return Error.new(options, self)
	end

	function Error:getErrorChain()
		local runtimeErrors = { self }

		while runtimeErrors[#runtimeErrors].parent do
			table.insert(runtimeErrors, runtimeErrors[#runtimeErrors].parent)
		end

		return runtimeErrors
	end

	function Error:__tostring()
		local errorStrings = {
			string.format("-- Promise.Error(%s) --", self.kind or "?"),
		}

		for _, runtimeError in ipairs(self:getErrorChain()) do
			table.insert(errorStrings, table.concat({
				runtimeError.trace or runtimeError.error,
				runtimeError.context,
			}, "\n"))
		end

		return table.concat(errorStrings, "\n")
	end
end
