-- Compiled with roblox-ts v3.0.0 local TS = _G[script] local isConstructor = TS.import(script, script.Parent, "utility").isConstructor --[[ * * Reflection/metadata API ]] local Reflect = {} do local _container = Reflect --* object -> property -> key -> value local metadata = setmetatable({}, { __mode = "k", }) local objToId = {} --* @internal local decorators = {} _container.decorators = decorators --* @internal local idToObj = {} _container.idToObj = idToObj local NO_PROP_MARKER = {} local function getObjMetadata(obj, prop, create) local _condition = prop if _condition == nil then _condition = NO_PROP_MARKER end local realProp = _condition if create then local _obj = obj local objMetadata = metadata[_obj] if not objMetadata then local _exp = obj objMetadata = {} local _objMetadata = objMetadata metadata[_exp] = _objMetadata end local propMetadata = objMetadata[realProp] if not propMetadata then local _objMetadata = objMetadata propMetadata = {} local _propMetadata = propMetadata _objMetadata[realProp] = _propMetadata end return propMetadata else local _obj = obj local _result = metadata[_obj] if _result ~= nil then _result = _result[realProp] end return _result end end local function getParentConstructor(obj) local metatable = getmetatable(obj) if metatable and type(metatable) == "table" then return rawget(metatable, "__index") end end --[[ * * Apply metadata onto this object. ]] local function defineMetadata(obj, key, value, property) -- 'identifier' is a special, unique ID across all metadata classes. if key == "identifier" then local _value = value local _arg0 = type(_value) == "string" assert(_arg0, "identifier must be a string.") local _obj = obj local _arg0_1 = not (objToId[_obj] ~= nil) assert(_arg0_1, "obj is already registered.") local _value_1 = value local _arg0_2 = not (idToObj[_value_1] ~= nil) assert(_arg0_2, "id is already registered.") local _obj_1 = obj local _value_2 = value objToId[_obj_1] = _value_2 local _value_3 = value local _obj_2 = obj idToObj[_value_3] = _obj_2 end local metadata = getObjMetadata(obj, property, true) local _key = key local _value = value metadata[_key] = _value end _container.defineMetadata = defineMetadata --[[ * * Apply metadata in batch onto this object. ]] local function defineMetadataBatch(obj, list, property) local metadata = getObjMetadata(obj, property, true) for key, value in pairs(list) do metadata[key] = value end end _container.defineMetadataBatch = defineMetadataBatch --[[ * * Delete metadata from this object. ]] local function deleteMetadata(obj, key, property) local metadata = getObjMetadata(obj, property) local _result = metadata if _result ~= nil then local _key = key _result[_key] = nil end end _container.deleteMetadata = deleteMetadata --[[ * * Get metadata from this object. * Type parameter is an assertion. ]] local function getOwnMetadata(obj, key, property) local metadata = getObjMetadata(obj, property) local _result = metadata if _result ~= nil then local _key = key _result = _result[_key] end return _result end _container.getOwnMetadata = getOwnMetadata --[[ * * Check if this object has the specified metadata key. ]] local function hasOwnMetadata(obj, key, property) local metadata = getObjMetadata(obj, property) local _result = metadata if _result ~= nil then local _key = key _result = _result[_key] ~= nil end local _condition = _result if _condition == nil then _condition = false end return _condition end _container.hasOwnMetadata = hasOwnMetadata --[[ * * Retrieve all metadata keys for this object. ]] local function getOwnMetadataKeys(obj, property) local metadata = getObjMetadata(obj, property) local keys = {} local _result = metadata if _result ~= nil then -- ▼ ReadonlyMap.forEach ▼ local _callback = function(_, key) local _key = key table.insert(keys, _key) return #keys end for _k, _v in _result do _callback(_v, _k, _result) end -- ▲ ReadonlyMap.forEach ▲ end return keys end _container.getOwnMetadataKeys = getOwnMetadataKeys --[[ * * Retrieves all properties (that contain metadata) on this object. ]] local function getOwnProperties(obj) local _obj = obj local properties = metadata[_obj] if not properties then return {} end local keys = {} for key in properties do if key ~= NO_PROP_MARKER then table.insert(keys, key) end end return keys end _container.getOwnProperties = getOwnProperties --[[ * * Retrieve all values for the specified key from the object and its parents. * Type parameter is an assertion. ]] local function getMetadatas(obj, key, property) local values = {} local value = getOwnMetadata(obj, key, property) if value ~= nil then table.insert(values, value) end local parent = getParentConstructor(obj) if parent then local _exp = getMetadatas(parent, key, property) -- ▼ ReadonlyArray.forEach ▼ local _callback = function(value) local _value = value table.insert(values, _value) return #values end for _k, _v in _exp do _callback(_v, _k - 1, _exp) end -- ▲ ReadonlyArray.forEach ▲ end return values end _container.getMetadatas = getMetadatas --[[ * * Get metadata from this object or its parents. * Type parameter is an assertion. ]] local function getMetadata(obj, key, property) local value = getOwnMetadata(obj, key, property) if value ~= nil then return value end local parent = getParentConstructor(obj) if parent then return getMetadata(parent, key, property) end end _container.getMetadata = getMetadata --[[ * * Check if this object or any of its parents has the specified metadata key. ]] local function hasMetadata(obj, key, property) local value = hasOwnMetadata(obj, key, property) if value then return value end local parent = getParentConstructor(obj) if parent then return hasMetadata(parent, key, property) end return false end _container.hasMetadata = hasMetadata --[[ * * Retrieve all metadata keys for this object and its parents. ]] local function getMetadataKeys(obj, property) local _set = {} for _, _v in getOwnMetadataKeys(obj, property) do _set[_v] = true end local keys = _set local parent = getParentConstructor(obj) if parent then local _exp = getMetadataKeys(parent, property) -- ▼ ReadonlyArray.forEach ▼ local _callback = function(key) local _key = key keys[_key] = true return keys end for _k, _v in _exp do _callback(_v, _k - 1, _exp) end -- ▲ ReadonlyArray.forEach ▲ end local _array = {} local _length = #_array for _v in keys do _length += 1 _array[_length] = _v end return _array end _container.getMetadataKeys = getMetadataKeys --[[ * * Retrieves all properties (that contain metadata) on this object and its parents. ]] local function getProperties(obj) local _set = {} for _, _v in getOwnProperties(obj) do _set[_v] = true end local keys = _set local parent = getParentConstructor(obj) if parent then local _exp = getProperties(parent) -- ▼ ReadonlyArray.forEach ▼ local _callback = function(key) local _key = key keys[_key] = true return keys end for _k, _v in _exp do _callback(_v, _k - 1, _exp) end -- ▲ ReadonlyArray.forEach ▲ end local _array = {} local _length = #_array for _v in keys do _length += 1 _array[_length] = _v end return _array end _container.getProperties = getProperties --* @hidden local function decorate(object, id, rawDecoration, args, property, isStatic) if isStatic == nil then isStatic = false end local decoration = rawDecoration local descriptor = { id = id, isStatic = isStatic, object = object, constructor = if isConstructor(object) then object else nil, property = property, } if property == nil then local _id = id local decoratedObjects = decorators[_id] if not decoratedObjects then local _exp = id decoratedObjects = {} local _decoratedObjects = decoratedObjects decorators[_exp] = _decoratedObjects end local _decoratedObjects = decoratedObjects local _object = object table.insert(_decoratedObjects, _object) end decoration.func(descriptor, args) end _container.decorate = decorate --* @hidden Internal use, do not use local function resetObject(object) local _object = object local id = objToId[_object] if id ~= nil then local _object_1 = object objToId[_object_1] = nil idToObj[id] = nil end local _object_1 = object metadata[_object_1] = nil end _container.resetObject = resetObject end return { Reflect = Reflect, }