roblox-opencode 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/README.md +112 -122
  2. package/commands/setup-game.md +108 -108
  3. package/commands/sync-check.md +53 -53
  4. package/core/roblox-core.md +93 -93
  5. package/dist/server.js +189 -167
  6. package/package.json +35 -35
  7. package/skills/roblox-analytics/SKILL.md +277 -277
  8. package/skills/roblox-analytics/references/event-batcher.luau +75 -75
  9. package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
  10. package/skills/roblox-architecture/SKILL.md +877 -863
  11. package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
  12. package/skills/roblox-code-review/SKILL.md +686 -686
  13. package/skills/roblox-data/SKILL.md +889 -889
  14. package/skills/roblox-data/references/inventory-systems.md +1729 -1729
  15. package/skills/roblox-debug/SKILL.md +98 -98
  16. package/skills/roblox-gui/SKILL.md +1103 -1103
  17. package/skills/roblox-gui-fusion/SKILL.md +150 -150
  18. package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
  19. package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
  20. package/skills/roblox-gui-fusion/references/shop.luau +411 -411
  21. package/skills/roblox-luau-mastery/SKILL.md +1618 -1519
  22. package/skills/roblox-monetization/SKILL.md +1084 -1084
  23. package/skills/roblox-monetization/references/process-receipt.luau +131 -131
  24. package/skills/roblox-networking/SKILL.md +669 -669
  25. package/skills/roblox-networking/references/remote-validator.luau +193 -193
  26. package/skills/roblox-publish-checklist/SKILL.md +127 -127
  27. package/skills/roblox-runtime/SKILL.md +753 -753
  28. package/skills/roblox-sharp-edges/SKILL.md +294 -294
  29. package/skills/roblox-sync/SKILL.md +126 -126
  30. package/skills/roblox-testing/SKILL.md +943 -943
  31. package/skills/roblox-tooling/SKILL.md +149 -149
  32. package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
  33. package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
  34. package/vendor/LICENSES/promise-LICENSE +20 -20
  35. package/vendor/LICENSES/t-LICENSE +21 -21
  36. package/vendor/LICENSES/testez-LICENSE +200 -200
  37. package/vendor/README.md +83 -83
  38. package/vendor/fusion/Animation/ExternalTime.luau +83 -83
  39. package/vendor/fusion/Animation/Spring.luau +321 -321
  40. package/vendor/fusion/Animation/Stopwatch.luau +127 -127
  41. package/vendor/fusion/Animation/Tween.luau +187 -187
  42. package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
  43. package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
  44. package/vendor/fusion/Animation/lerpType.luau +163 -163
  45. package/vendor/fusion/Animation/packType.luau +99 -99
  46. package/vendor/fusion/Animation/springCoefficients.luau +80 -80
  47. package/vendor/fusion/Animation/unpackType.luau +102 -102
  48. package/vendor/fusion/Colour/Oklab.luau +70 -70
  49. package/vendor/fusion/Colour/sRGB.luau +54 -54
  50. package/vendor/fusion/External.luau +167 -167
  51. package/vendor/fusion/ExternalDebug.luau +69 -69
  52. package/vendor/fusion/Graph/Observer.luau +113 -113
  53. package/vendor/fusion/Graph/castToGraph.luau +28 -28
  54. package/vendor/fusion/Graph/change.luau +80 -80
  55. package/vendor/fusion/Graph/depend.luau +32 -32
  56. package/vendor/fusion/Graph/evaluate.luau +55 -55
  57. package/vendor/fusion/Instances/Attribute.luau +57 -57
  58. package/vendor/fusion/Instances/AttributeChange.luau +46 -46
  59. package/vendor/fusion/Instances/AttributeOut.luau +63 -63
  60. package/vendor/fusion/Instances/Child.luau +21 -21
  61. package/vendor/fusion/Instances/Children.luau +147 -147
  62. package/vendor/fusion/Instances/Hydrate.luau +32 -32
  63. package/vendor/fusion/Instances/New.luau +52 -52
  64. package/vendor/fusion/Instances/OnChange.luau +49 -49
  65. package/vendor/fusion/Instances/OnEvent.luau +53 -53
  66. package/vendor/fusion/Instances/Out.luau +69 -69
  67. package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
  68. package/vendor/fusion/Instances/defaultProps.luau +194 -194
  69. package/vendor/fusion/LICENSE +21 -21
  70. package/vendor/fusion/Logging/formatError.luau +48 -48
  71. package/vendor/fusion/Logging/messages.luau +51 -51
  72. package/vendor/fusion/Logging/parseError.luau +24 -24
  73. package/vendor/fusion/Memory/checkLifetime.luau +133 -133
  74. package/vendor/fusion/Memory/deriveScope.luau +23 -23
  75. package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
  76. package/vendor/fusion/Memory/doCleanup.luau +78 -78
  77. package/vendor/fusion/Memory/innerScope.luau +33 -33
  78. package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
  79. package/vendor/fusion/Memory/needsDestruction.luau +16 -16
  80. package/vendor/fusion/Memory/poisonScope.luau +33 -33
  81. package/vendor/fusion/Memory/scopePool.luau +54 -54
  82. package/vendor/fusion/Memory/scoped.luau +26 -26
  83. package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
  84. package/vendor/fusion/RobloxExternal.luau +97 -97
  85. package/vendor/fusion/State/Computed.luau +138 -138
  86. package/vendor/fusion/State/For/Disassembly.luau +210 -210
  87. package/vendor/fusion/State/For/ForTypes.luau +30 -30
  88. package/vendor/fusion/State/For/init.luau +109 -109
  89. package/vendor/fusion/State/ForKeys.luau +93 -93
  90. package/vendor/fusion/State/ForPairs.luau +96 -96
  91. package/vendor/fusion/State/ForValues.luau +93 -93
  92. package/vendor/fusion/State/Value.luau +87 -87
  93. package/vendor/fusion/State/castToState.luau +25 -25
  94. package/vendor/fusion/State/peek.luau +30 -30
  95. package/vendor/fusion/Types.luau +314 -314
  96. package/vendor/fusion/Utility/Contextual.luau +90 -90
  97. package/vendor/fusion/Utility/Safe.luau +22 -22
  98. package/vendor/fusion/Utility/isSimilar.luau +29 -29
  99. package/vendor/fusion/Utility/merge.luau +35 -35
  100. package/vendor/fusion/Utility/nameOf.luau +34 -34
  101. package/vendor/fusion/Utility/never.luau +13 -13
  102. package/vendor/fusion/Utility/nicknames.luau +10 -10
  103. package/vendor/fusion/Utility/xtypeof.luau +26 -26
  104. package/vendor/fusion/init.luau +82 -82
  105. package/vendor/profilestore/init.luau +2242 -2242
  106. package/vendor/promise/init.luau +1982 -1982
  107. package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
  108. package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
  109. package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
  110. package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
  111. package/vendor/rbxutil/buffer-util/Types.luau +60 -60
  112. package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
  113. package/vendor/rbxutil/buffer-util/init.luau +41 -41
  114. package/vendor/rbxutil/buffer-util/package.json +16 -16
  115. package/vendor/rbxutil/buffer-util/wally.toml +9 -9
  116. package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
  117. package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
  118. package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
  119. package/vendor/rbxutil/comm/Client/init.luau +135 -135
  120. package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
  121. package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
  122. package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
  123. package/vendor/rbxutil/comm/Server/init.luau +140 -140
  124. package/vendor/rbxutil/comm/Types.luau +18 -18
  125. package/vendor/rbxutil/comm/Util.luau +27 -27
  126. package/vendor/rbxutil/comm/init.luau +35 -35
  127. package/vendor/rbxutil/comm/wally.toml +13 -13
  128. package/vendor/rbxutil/component/init.luau +759 -759
  129. package/vendor/rbxutil/component/init.test.luau +311 -311
  130. package/vendor/rbxutil/component/wally.toml +14 -14
  131. package/vendor/rbxutil/concur/init.luau +542 -542
  132. package/vendor/rbxutil/concur/init.test.luau +364 -364
  133. package/vendor/rbxutil/concur/wally.toml +8 -8
  134. package/vendor/rbxutil/enum-list/init.luau +101 -101
  135. package/vendor/rbxutil/enum-list/init.test.luau +91 -91
  136. package/vendor/rbxutil/enum-list/wally.toml +8 -8
  137. package/vendor/rbxutil/find/index.d.ts +20 -20
  138. package/vendor/rbxutil/find/init.luau +44 -44
  139. package/vendor/rbxutil/find/package.json +17 -17
  140. package/vendor/rbxutil/find/wally.toml +8 -8
  141. package/vendor/rbxutil/input/Gamepad.luau +559 -559
  142. package/vendor/rbxutil/input/Keyboard.luau +124 -124
  143. package/vendor/rbxutil/input/Mouse.luau +278 -278
  144. package/vendor/rbxutil/input/PreferredInput.luau +91 -91
  145. package/vendor/rbxutil/input/Touch.luau +120 -120
  146. package/vendor/rbxutil/input/init.luau +33 -33
  147. package/vendor/rbxutil/input/wally.toml +12 -12
  148. package/vendor/rbxutil/loader/index.d.ts +15 -15
  149. package/vendor/rbxutil/loader/init.luau +137 -137
  150. package/vendor/rbxutil/loader/wally.toml +8 -8
  151. package/vendor/rbxutil/log/index.d.ts +38 -38
  152. package/vendor/rbxutil/log/init.luau +746 -746
  153. package/vendor/rbxutil/log/wally.toml +8 -8
  154. package/vendor/rbxutil/net/init.luau +190 -190
  155. package/vendor/rbxutil/net/wally.toml +8 -8
  156. package/vendor/rbxutil/option/index.d.ts +44 -44
  157. package/vendor/rbxutil/option/init.luau +489 -489
  158. package/vendor/rbxutil/option/init.test.luau +342 -342
  159. package/vendor/rbxutil/option/wally.toml +8 -8
  160. package/vendor/rbxutil/pid/index.d.ts +53 -53
  161. package/vendor/rbxutil/pid/init.luau +195 -195
  162. package/vendor/rbxutil/pid/package.json +16 -16
  163. package/vendor/rbxutil/pid/wally.toml +9 -9
  164. package/vendor/rbxutil/quaternion/index.d.ts +117 -117
  165. package/vendor/rbxutil/quaternion/init.luau +570 -570
  166. package/vendor/rbxutil/quaternion/package.json +16 -16
  167. package/vendor/rbxutil/quaternion/wally.toml +9 -9
  168. package/vendor/rbxutil/query/index.d.ts +43 -43
  169. package/vendor/rbxutil/query/init.luau +117 -117
  170. package/vendor/rbxutil/query/package.json +18 -18
  171. package/vendor/rbxutil/query/wally.toml +9 -9
  172. package/vendor/rbxutil/sequent/index.d.ts +28 -28
  173. package/vendor/rbxutil/sequent/init.luau +340 -340
  174. package/vendor/rbxutil/sequent/package.json +16 -16
  175. package/vendor/rbxutil/sequent/wally.toml +9 -9
  176. package/vendor/rbxutil/ser/init.luau +175 -175
  177. package/vendor/rbxutil/ser/init.test.luau +50 -50
  178. package/vendor/rbxutil/ser/wally.toml +11 -11
  179. package/vendor/rbxutil/shake/index.d.ts +36 -36
  180. package/vendor/rbxutil/shake/init.luau +532 -532
  181. package/vendor/rbxutil/shake/init.test.luau +267 -267
  182. package/vendor/rbxutil/shake/package.json +16 -16
  183. package/vendor/rbxutil/shake/wally.toml +9 -9
  184. package/vendor/rbxutil/signal/index.d.ts +100 -100
  185. package/vendor/rbxutil/signal/init.luau +432 -432
  186. package/vendor/rbxutil/signal/init.test.luau +190 -190
  187. package/vendor/rbxutil/signal/package.json +17 -17
  188. package/vendor/rbxutil/signal/wally.toml +9 -9
  189. package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
  190. package/vendor/rbxutil/silo/Util.luau +55 -55
  191. package/vendor/rbxutil/silo/init.luau +338 -338
  192. package/vendor/rbxutil/silo/init.test.luau +215 -215
  193. package/vendor/rbxutil/silo/wally.toml +8 -8
  194. package/vendor/rbxutil/spring/index.d.ts +40 -40
  195. package/vendor/rbxutil/spring/init.luau +97 -97
  196. package/vendor/rbxutil/spring/package.json +17 -17
  197. package/vendor/rbxutil/spring/wally.toml +8 -8
  198. package/vendor/rbxutil/stream/index.d.ts +88 -88
  199. package/vendor/rbxutil/stream/init.luau +597 -597
  200. package/vendor/rbxutil/stream/package.json +18 -18
  201. package/vendor/rbxutil/stream/wally.toml +9 -9
  202. package/vendor/rbxutil/streamable/Streamable.luau +202 -202
  203. package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
  204. package/vendor/rbxutil/streamable/init.luau +8 -8
  205. package/vendor/rbxutil/streamable/wally.toml +12 -12
  206. package/vendor/rbxutil/symbol/init.luau +56 -56
  207. package/vendor/rbxutil/symbol/init.test.luau +37 -37
  208. package/vendor/rbxutil/symbol/wally.toml +8 -8
  209. package/vendor/rbxutil/table-util/init.luau +938 -938
  210. package/vendor/rbxutil/table-util/init.test.luau +439 -439
  211. package/vendor/rbxutil/task-queue/index.d.ts +27 -27
  212. package/vendor/rbxutil/task-queue/init.luau +97 -97
  213. package/vendor/rbxutil/task-queue/wally.toml +8 -8
  214. package/vendor/rbxutil/timer/index.d.ts +81 -81
  215. package/vendor/rbxutil/timer/init.luau +249 -249
  216. package/vendor/rbxutil/timer/init.test.luau +73 -73
  217. package/vendor/rbxutil/timer/wally.toml +11 -11
  218. package/vendor/rbxutil/tree/index.d.ts +15 -15
  219. package/vendor/rbxutil/tree/init.luau +137 -137
  220. package/vendor/rbxutil/tree/wally.toml +8 -8
  221. package/vendor/rbxutil/trove/index.d.ts +46 -46
  222. package/vendor/rbxutil/trove/init.luau +787 -787
  223. package/vendor/rbxutil/trove/init.test.luau +203 -203
  224. package/vendor/rbxutil/trove/wally.toml +8 -8
  225. package/vendor/rbxutil/typed-remote/init.luau +196 -196
  226. package/vendor/rbxutil/typed-remote/wally.toml +8 -8
  227. package/vendor/rbxutil/wait-for/index.d.ts +17 -17
  228. package/vendor/rbxutil/wait-for/init.luau +257 -257
  229. package/vendor/rbxutil/wait-for/init.test.luau +182 -182
  230. package/vendor/rbxutil/wait-for/wally.toml +11 -11
  231. package/vendor/t/t.lua +1350 -1350
  232. package/vendor/testez/Context.lua +26 -26
  233. package/vendor/testez/Expectation.lua +311 -311
  234. package/vendor/testez/ExpectationContext.lua +38 -38
  235. package/vendor/testez/LifecycleHooks.lua +89 -89
  236. package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
  237. package/vendor/testez/Reporters/TextReporter.lua +105 -105
  238. package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
  239. package/vendor/testez/TestBootstrap.lua +146 -146
  240. package/vendor/testez/TestEnum.lua +27 -27
  241. package/vendor/testez/TestPlan.lua +304 -304
  242. package/vendor/testez/TestPlanner.lua +39 -39
  243. package/vendor/testez/TestResults.lua +111 -111
  244. package/vendor/testez/TestRunner.lua +188 -188
  245. package/vendor/testez/TestSession.lua +243 -243
  246. package/vendor/testez/init.lua +39 -39
@@ -1,211 +1,211 @@
1
- --!strict
2
- --!nolint LocalUnused
3
- --!nolint LocalShadow
4
- local task = nil -- Disable usage of Roblox's task scheduler
5
-
6
- --[[
7
- Breaks down an input table into reactive sub-objects for each pair.
8
- ]]
9
-
10
- local Package = script.Parent.Parent.Parent
11
- local Types = require(Package.Types)
12
- local External = require(Package.External)
13
- -- Graph
14
- local depend = require(Package.Graph.depend)
15
- -- State
16
- local peek = require(Package.State.peek)
17
- local castToState = require(Package.State.castToState)
18
- local ForTypes = require(Package.State.For.ForTypes)
19
- -- Memory
20
- local doCleanup = require(Package.Memory.doCleanup)
21
- local deriveScope = require(Package.Memory.deriveScope)
22
- local scopePool = require(Package.Memory.scopePool)
23
- -- Utility
24
- local nameOf = require(Package.Utility.nameOf)
25
- local nicknames = require(Package.Utility.nicknames)
26
-
27
- type Self<S, KI, KO, VI, VO> = ForTypes.Disassembly<S, KI, KO, VI, KO> & {
28
- scope: (S & Types.Scope<unknown>)?,
29
- _inputTable: Types.UsedAs<{[KI]: VI}>,
30
- _constructor: (
31
- Types.Scope<S>,
32
- initialKey: KI,
33
- initialValue: VI
34
- ) -> ForTypes.SubObject<S, KI, KO, VI, VO>,
35
- _subObjects: {[ForTypes.SubObject<S, KI, KO, VI, VO>]: true}
36
- }
37
-
38
-
39
- local class = {}
40
- class.type = "Graph"
41
- class.kind = "For.Disassembly"
42
- class.timeliness = "lazy"
43
-
44
- local METATABLE = table.freeze {__index = class}
45
-
46
- local function Disassembly<S, KI, KO, VI, VO>(
47
- scope: S & Types.Scope<unknown>,
48
- inputTable: Types.UsedAs<{[KI]: VI}>,
49
- constructor: (
50
- Types.Scope<S>,
51
- initialKey: KI,
52
- initialValue: VI
53
- ) -> ForTypes.SubObject<S, KI, KO, VI, VO>
54
- ): ForTypes.Disassembly<S, KI, KO, VI, KO>
55
- local createdAt = os.clock()
56
- local self = setmetatable(
57
- {
58
- createdAt = createdAt,
59
- dependencySet = {},
60
- dependentSet = {},
61
- scope = scope,
62
- validity = "invalid",
63
- _inputTable = inputTable,
64
- _constructor = constructor,
65
- _subObjects = {}
66
- },
67
- METATABLE
68
- ) :: any
69
-
70
- local destroy = function()
71
- self.scope = nil
72
- for dependency in pairs(self.dependencySet) do
73
- dependency.dependentSet[self] = nil
74
- end
75
- for subObject in self._subObjects do
76
- if subObject.maybeScope ~= nil then
77
- doCleanup(subObject.maybeScope)
78
- subObject.maybeScope = nil
79
- end
80
- end
81
- end
82
- self.oldestTask = destroy
83
- nicknames[self.oldestTask] = "For (internal disassembler)"
84
- table.insert(scope, destroy)
85
-
86
- return self
87
- end
88
-
89
- function class.populate<S, KI, KO, VI, VO>(
90
- self: Self<S, KI, KO, VI, VO>,
91
- use: Types.Use,
92
- output: {[KO]: VO}
93
- ): ()
94
- local minArrayIndex = math.huge
95
- local maxArrayIndex = -math.huge
96
- local hasHoles = false
97
- for subObject in self._subObjects do
98
- local outputKey, outputValue = subObject:useOutputPair(use)
99
- if outputKey == nil or outputValue == nil then
100
- hasHoles = true
101
- continue
102
- elseif output[outputKey] ~= nil then
103
- External.logErrorNonFatal("forKeyCollision", nil, tostring(outputKey))
104
- continue
105
- end
106
- output[outputKey] = outputValue
107
- if typeof(outputKey) == "number" then
108
- minArrayIndex = math.min(minArrayIndex, outputKey)
109
- maxArrayIndex = math.max(maxArrayIndex, outputKey)
110
- end
111
- end
112
- -- Be careful of NaN here
113
- if hasHoles and maxArrayIndex > minArrayIndex then
114
- local output: {[number]: VO} = output :: any
115
- local moveToIndex = minArrayIndex
116
- for moveFromIndex = minArrayIndex, maxArrayIndex do
117
- local outputValue = output[moveFromIndex]
118
- if outputValue == nil then
119
- continue
120
- end
121
- -- The ordering is important in case the indices are the same
122
- output[moveFromIndex] = nil
123
- output[moveToIndex] = outputValue
124
- moveToIndex += 1
125
- end
126
- end
127
- end
128
-
129
- function class._evaluate<S, KI, KO, VI, VO>(
130
- self: Self<S, KI, KO, VI, VO>
131
- ): boolean
132
- local outerScope = self.scope :: S & Types.Scope<unknown>
133
- local inputState = castToState(self._inputTable)
134
- if inputState ~= nil then
135
- if inputState.scope == nil then
136
- External.logError(
137
- "useAfterDestroy",
138
- nil,
139
- `The input {nameOf(inputState, "table")}`,
140
- `the For object that is watching it`
141
- )
142
- end
143
- depend(self, inputState)
144
- end
145
-
146
- local pendingPairs = {} :: {[KI]: VI}
147
- for key, value in peek(self._inputTable) do
148
- pendingPairs[key] = value
149
- end
150
-
151
- local newSubObjects = {} :: typeof(self._subObjects)
152
-
153
- for subObject in self._subObjects do
154
- local reused = false
155
- local oldInputKey = subObject.inputKey
156
- local oldInputValue = subObject.inputValue
157
- local newInputKey: KI
158
- -- Reuse when the keys are identical.
159
- if not subObject.roamKeys and pendingPairs[oldInputKey] ~= nil then
160
- reused = true
161
- newInputKey = oldInputKey
162
- else -- Try and reuse some other pair instead.
163
- for pendingKey, pendingValue in pendingPairs do
164
- reused = true
165
- newInputKey = pendingKey
166
- if subObject.roamValues then
167
- break
168
- end
169
- if pendingValue == oldInputValue then
170
- -- If the values are the same, then no need to update those,
171
- -- so prefer this choice to any other.
172
- break
173
- end
174
- end
175
- end
176
- if reused then
177
- local newInputValue = pendingPairs[newInputKey]
178
- newSubObjects[subObject] = true
179
- if newInputKey ~= oldInputKey then
180
- subObject.inputKey = newInputKey
181
- subObject:invalidateInputKey()
182
- end
183
- if newInputValue ~= oldInputValue then
184
- subObject.inputValue = newInputValue
185
- subObject:invalidateInputValue()
186
- end
187
- pendingPairs[newInputKey] = nil
188
- else -- Too many sub objects for the number of pairs.
189
- if subObject.maybeScope ~= nil then
190
- doCleanup(subObject.maybeScope)
191
- subObject.maybeScope = nil
192
- end
193
- end
194
- end
195
-
196
- -- Generate new objects if needed to cover the remaining pending pairs.
197
- for pendingKey, pendingValue in pendingPairs do
198
- local subObject = self._constructor(deriveScope(outerScope), pendingKey, pendingValue)
199
- if subObject.maybeScope ~= nil then
200
- subObject.maybeScope = scopePool.giveIfEmpty(subObject.maybeScope)
201
- end
202
- newSubObjects[subObject] = true
203
- end
204
-
205
- self._subObjects = newSubObjects
206
-
207
- return true
208
- end
209
-
210
- table.freeze(class)
1
+ --!strict
2
+ --!nolint LocalUnused
3
+ --!nolint LocalShadow
4
+ local task = nil -- Disable usage of Roblox's task scheduler
5
+
6
+ --[[
7
+ Breaks down an input table into reactive sub-objects for each pair.
8
+ ]]
9
+
10
+ local Package = script.Parent.Parent.Parent
11
+ local Types = require(Package.Types)
12
+ local External = require(Package.External)
13
+ -- Graph
14
+ local depend = require(Package.Graph.depend)
15
+ -- State
16
+ local peek = require(Package.State.peek)
17
+ local castToState = require(Package.State.castToState)
18
+ local ForTypes = require(Package.State.For.ForTypes)
19
+ -- Memory
20
+ local doCleanup = require(Package.Memory.doCleanup)
21
+ local deriveScope = require(Package.Memory.deriveScope)
22
+ local scopePool = require(Package.Memory.scopePool)
23
+ -- Utility
24
+ local nameOf = require(Package.Utility.nameOf)
25
+ local nicknames = require(Package.Utility.nicknames)
26
+
27
+ type Self<S, KI, KO, VI, VO> = ForTypes.Disassembly<S, KI, KO, VI, KO> & {
28
+ scope: (S & Types.Scope<unknown>)?,
29
+ _inputTable: Types.UsedAs<{[KI]: VI}>,
30
+ _constructor: (
31
+ Types.Scope<S>,
32
+ initialKey: KI,
33
+ initialValue: VI
34
+ ) -> ForTypes.SubObject<S, KI, KO, VI, VO>,
35
+ _subObjects: {[ForTypes.SubObject<S, KI, KO, VI, VO>]: true}
36
+ }
37
+
38
+
39
+ local class = {}
40
+ class.type = "Graph"
41
+ class.kind = "For.Disassembly"
42
+ class.timeliness = "lazy"
43
+
44
+ local METATABLE = table.freeze {__index = class}
45
+
46
+ local function Disassembly<S, KI, KO, VI, VO>(
47
+ scope: S & Types.Scope<unknown>,
48
+ inputTable: Types.UsedAs<{[KI]: VI}>,
49
+ constructor: (
50
+ Types.Scope<S>,
51
+ initialKey: KI,
52
+ initialValue: VI
53
+ ) -> ForTypes.SubObject<S, KI, KO, VI, VO>
54
+ ): ForTypes.Disassembly<S, KI, KO, VI, KO>
55
+ local createdAt = os.clock()
56
+ local self = setmetatable(
57
+ {
58
+ createdAt = createdAt,
59
+ dependencySet = {},
60
+ dependentSet = {},
61
+ scope = scope,
62
+ validity = "invalid",
63
+ _inputTable = inputTable,
64
+ _constructor = constructor,
65
+ _subObjects = {}
66
+ },
67
+ METATABLE
68
+ ) :: any
69
+
70
+ local destroy = function()
71
+ self.scope = nil
72
+ for dependency in pairs(self.dependencySet) do
73
+ dependency.dependentSet[self] = nil
74
+ end
75
+ for subObject in self._subObjects do
76
+ if subObject.maybeScope ~= nil then
77
+ doCleanup(subObject.maybeScope)
78
+ subObject.maybeScope = nil
79
+ end
80
+ end
81
+ end
82
+ self.oldestTask = destroy
83
+ nicknames[self.oldestTask] = "For (internal disassembler)"
84
+ table.insert(scope, destroy)
85
+
86
+ return self
87
+ end
88
+
89
+ function class.populate<S, KI, KO, VI, VO>(
90
+ self: Self<S, KI, KO, VI, VO>,
91
+ use: Types.Use,
92
+ output: {[KO]: VO}
93
+ ): ()
94
+ local minArrayIndex = math.huge
95
+ local maxArrayIndex = -math.huge
96
+ local hasHoles = false
97
+ for subObject in self._subObjects do
98
+ local outputKey, outputValue = subObject:useOutputPair(use)
99
+ if outputKey == nil or outputValue == nil then
100
+ hasHoles = true
101
+ continue
102
+ elseif output[outputKey] ~= nil then
103
+ External.logErrorNonFatal("forKeyCollision", nil, tostring(outputKey))
104
+ continue
105
+ end
106
+ output[outputKey] = outputValue
107
+ if typeof(outputKey) == "number" then
108
+ minArrayIndex = math.min(minArrayIndex, outputKey)
109
+ maxArrayIndex = math.max(maxArrayIndex, outputKey)
110
+ end
111
+ end
112
+ -- Be careful of NaN here
113
+ if hasHoles and maxArrayIndex > minArrayIndex then
114
+ local output: {[number]: VO} = output :: any
115
+ local moveToIndex = minArrayIndex
116
+ for moveFromIndex = minArrayIndex, maxArrayIndex do
117
+ local outputValue = output[moveFromIndex]
118
+ if outputValue == nil then
119
+ continue
120
+ end
121
+ -- The ordering is important in case the indices are the same
122
+ output[moveFromIndex] = nil
123
+ output[moveToIndex] = outputValue
124
+ moveToIndex += 1
125
+ end
126
+ end
127
+ end
128
+
129
+ function class._evaluate<S, KI, KO, VI, VO>(
130
+ self: Self<S, KI, KO, VI, VO>
131
+ ): boolean
132
+ local outerScope = self.scope :: S & Types.Scope<unknown>
133
+ local inputState = castToState(self._inputTable)
134
+ if inputState ~= nil then
135
+ if inputState.scope == nil then
136
+ External.logError(
137
+ "useAfterDestroy",
138
+ nil,
139
+ `The input {nameOf(inputState, "table")}`,
140
+ `the For object that is watching it`
141
+ )
142
+ end
143
+ depend(self, inputState)
144
+ end
145
+
146
+ local pendingPairs = {} :: {[KI]: VI}
147
+ for key, value in peek(self._inputTable) do
148
+ pendingPairs[key] = value
149
+ end
150
+
151
+ local newSubObjects = {} :: typeof(self._subObjects)
152
+
153
+ for subObject in self._subObjects do
154
+ local reused = false
155
+ local oldInputKey = subObject.inputKey
156
+ local oldInputValue = subObject.inputValue
157
+ local newInputKey: KI
158
+ -- Reuse when the keys are identical.
159
+ if not subObject.roamKeys and pendingPairs[oldInputKey] ~= nil then
160
+ reused = true
161
+ newInputKey = oldInputKey
162
+ else -- Try and reuse some other pair instead.
163
+ for pendingKey, pendingValue in pendingPairs do
164
+ reused = true
165
+ newInputKey = pendingKey
166
+ if subObject.roamValues then
167
+ break
168
+ end
169
+ if pendingValue == oldInputValue then
170
+ -- If the values are the same, then no need to update those,
171
+ -- so prefer this choice to any other.
172
+ break
173
+ end
174
+ end
175
+ end
176
+ if reused then
177
+ local newInputValue = pendingPairs[newInputKey]
178
+ newSubObjects[subObject] = true
179
+ if newInputKey ~= oldInputKey then
180
+ subObject.inputKey = newInputKey
181
+ subObject:invalidateInputKey()
182
+ end
183
+ if newInputValue ~= oldInputValue then
184
+ subObject.inputValue = newInputValue
185
+ subObject:invalidateInputValue()
186
+ end
187
+ pendingPairs[newInputKey] = nil
188
+ else -- Too many sub objects for the number of pairs.
189
+ if subObject.maybeScope ~= nil then
190
+ doCleanup(subObject.maybeScope)
191
+ subObject.maybeScope = nil
192
+ end
193
+ end
194
+ end
195
+
196
+ -- Generate new objects if needed to cover the remaining pending pairs.
197
+ for pendingKey, pendingValue in pendingPairs do
198
+ local subObject = self._constructor(deriveScope(outerScope), pendingKey, pendingValue)
199
+ if subObject.maybeScope ~= nil then
200
+ subObject.maybeScope = scopePool.giveIfEmpty(subObject.maybeScope)
201
+ end
202
+ newSubObjects[subObject] = true
203
+ end
204
+
205
+ self._subObjects = newSubObjects
206
+
207
+ return true
208
+ end
209
+
210
+ table.freeze(class)
211
211
  return Disassembly
@@ -1,30 +1,30 @@
1
- --!strict
2
- --!nolint LocalUnused
3
- --!nolint LocalShadow
4
- local task = nil -- Disable usage of Roblox's task scheduler
5
-
6
- --[[
7
- Stores types that are commonly used between For objects.
8
- ]]
9
-
10
- local Package = script.Parent.Parent.Parent
11
- local Types = require(Package.Types)
12
-
13
- export type SubObject<S, KI, KO, VI, VO> = {
14
- -- Not all sub objects need to store a scope, for example if the scope
15
- -- remains empty, it'll be given back to the scope pool.
16
- maybeScope: Types.Scope<S>?,
17
- inputKey: KI,
18
- inputValue: VI,
19
- roamKeys: boolean,
20
- roamValues: boolean,
21
- invalidateInputKey: (SubObject<S, KI, KO, VI, VO>) -> (),
22
- invalidateInputValue: (SubObject<S, KI, KO, VI, VO>) -> (),
23
- useOutputPair: (SubObject<S, KI, KO, VI, VO>, Types.Use) -> (KO?, VO?)
24
- }
25
-
26
- export type Disassembly<S, KI, KO, VI, VO> = Types.GraphObject & {
27
- populate: (Disassembly<S, KI, KO, VI, VO>, Types.Use, output: {[KO]: VO}) -> ()
28
- }
29
-
30
- return nil
1
+ --!strict
2
+ --!nolint LocalUnused
3
+ --!nolint LocalShadow
4
+ local task = nil -- Disable usage of Roblox's task scheduler
5
+
6
+ --[[
7
+ Stores types that are commonly used between For objects.
8
+ ]]
9
+
10
+ local Package = script.Parent.Parent.Parent
11
+ local Types = require(Package.Types)
12
+
13
+ export type SubObject<S, KI, KO, VI, VO> = {
14
+ -- Not all sub objects need to store a scope, for example if the scope
15
+ -- remains empty, it'll be given back to the scope pool.
16
+ maybeScope: Types.Scope<S>?,
17
+ inputKey: KI,
18
+ inputValue: VI,
19
+ roamKeys: boolean,
20
+ roamValues: boolean,
21
+ invalidateInputKey: (SubObject<S, KI, KO, VI, VO>) -> (),
22
+ invalidateInputValue: (SubObject<S, KI, KO, VI, VO>) -> (),
23
+ useOutputPair: (SubObject<S, KI, KO, VI, VO>, Types.Use) -> (KO?, VO?)
24
+ }
25
+
26
+ export type Disassembly<S, KI, KO, VI, VO> = Types.GraphObject & {
27
+ populate: (Disassembly<S, KI, KO, VI, VO>, Types.Use, output: {[KO]: VO}) -> ()
28
+ }
29
+
30
+ return nil