61 lines
1.4 KiB
Plaintext
61 lines
1.4 KiB
Plaintext
--!strict
|
|
|
|
--[[
|
|
Constructs and returns objects which can be used to model independent
|
|
reactive state.
|
|
]]
|
|
|
|
local Types = require "../Types"
|
|
-- Logging
|
|
local logError = require "../Logging/logError"
|
|
-- State
|
|
local updateAll = require "../State/updateAll"
|
|
-- Utility
|
|
local isSimilar = require "../Utility/isSimilar"
|
|
|
|
local class = {}
|
|
|
|
local CLASS_METATABLE = { __index = class }
|
|
local WEAK_KEYS_METATABLE = { __mode = "k" }
|
|
|
|
--[[
|
|
Updates the value stored in this State object.
|
|
|
|
If `force` is enabled, this will skip equality checks and always update the
|
|
state object and any dependents - use this with care as this can lead to
|
|
unnecessary updates.
|
|
]]
|
|
function class:set(newValue: any, force: boolean?)
|
|
local oldValue = self._value
|
|
if force or not isSimilar(oldValue, newValue) then
|
|
self._value = newValue
|
|
updateAll(self)
|
|
end
|
|
end
|
|
|
|
--[[
|
|
Returns the interior value of this state object.
|
|
]]
|
|
function class:_peek(): any
|
|
return self._value
|
|
end
|
|
|
|
function class:get()
|
|
logError "stateGetWasRemoved"
|
|
end
|
|
|
|
local function Value<T>(initialValue: T): Types.State<T>
|
|
local self = setmetatable({
|
|
type = "State",
|
|
kind = "Value",
|
|
-- if we held strong references to the dependents, then they wouldn't be
|
|
-- able to get garbage collected when they fall out of scope
|
|
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
|
|
_value = initialValue,
|
|
}, CLASS_METATABLE)
|
|
|
|
return self
|
|
end
|
|
|
|
return Value
|