@trioforge/crucible 0.0.0-stage → 0.2.0
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.
- package/LICENSE +21 -0
- package/client/package.json +4 -0
- package/emit/package.json +4 -0
- package/out/all.d.ts +7 -0
- package/out/all.luau +2 -0
- package/out/attribute.d.ts +7 -0
- package/out/attribute.luau +7 -0
- package/out/client/index.d.ts +10 -0
- package/out/client/init.luau +55 -0
- package/out/configs.d.ts +37 -0
- package/out/configs.luau +46 -0
- package/out/crucible-behaviour.d.ts +16 -0
- package/out/crucible-behaviour.luau +78 -0
- package/out/crucible-object.d.ts +10 -0
- package/out/crucible-object.luau +69 -0
- package/out/data.d.ts +224 -0
- package/out/data.luau +97 -0
- package/out/emit/configs.d.ts +4 -0
- package/out/emit/configs.luau +22 -0
- package/out/emit/data.d.ts +6 -0
- package/out/emit/data.luau +19 -0
- package/out/emit/index.d.ts +45 -0
- package/out/emit/init.luau +101 -0
- package/out/emit/network.d.ts +6 -0
- package/out/emit/network.luau +36 -0
- package/out/emit/replicated.d.ts +4 -0
- package/out/emit/replicated.luau +13 -0
- package/out/index.d.ts +20 -0
- package/out/init.luau +34 -0
- package/out/inject.d.ts +1 -0
- package/out/inject.luau +7 -0
- package/out/internal/binding.d.ts +1 -0
- package/out/internal/binding.luau +615 -0
- package/out/internal/boot.d.ts +1 -0
- package/out/internal/boot.luau +562 -0
- package/out/internal/configs/limits.d.ts +10 -0
- package/out/internal/configs/limits.luau +25 -0
- package/out/internal/configs/port.d.ts +29 -0
- package/out/internal/configs/port.luau +99 -0
- package/out/internal/configs/runtime.d.ts +21 -0
- package/out/internal/configs/runtime.luau +981 -0
- package/out/internal/construction-claim.d.ts +1 -0
- package/out/internal/construction-claim.luau +26 -0
- package/out/internal/data/admission.d.ts +1 -0
- package/out/internal/data/admission.luau +673 -0
- package/out/internal/data/declarations.d.ts +1 -0
- package/out/internal/data/declarations.luau +384 -0
- package/out/internal/data/envelope.d.ts +1 -0
- package/out/internal/data/envelope.luau +318 -0
- package/out/internal/data/handles.d.ts +1 -0
- package/out/internal/data/handles.luau +255 -0
- package/out/internal/data/inbox-transforms.d.ts +1 -0
- package/out/internal/data/inbox-transforms.luau +458 -0
- package/out/internal/data/inbox.d.ts +1 -0
- package/out/internal/data/inbox.luau +437 -0
- package/out/internal/data/lease.d.ts +1 -0
- package/out/internal/data/lease.luau +304 -0
- package/out/internal/data/limits.d.ts +1 -0
- package/out/internal/data/limits.luau +234 -0
- package/out/internal/data/messages.d.ts +1 -0
- package/out/internal/data/messages.luau +69 -0
- package/out/internal/data/operation-id.d.ts +1 -0
- package/out/internal/data/operation-id.luau +61 -0
- package/out/internal/data/paths.d.ts +2 -0
- package/out/internal/data/paths.luau +323 -0
- package/out/internal/data/port.d.ts +1 -0
- package/out/internal/data/port.luau +290 -0
- package/out/internal/data/profiles.d.ts +1 -0
- package/out/internal/data/profiles.luau +862 -0
- package/out/internal/data/receipts.d.ts +1 -0
- package/out/internal/data/receipts.luau +190 -0
- package/out/internal/data/record-bindings.d.ts +1 -0
- package/out/internal/data/record-bindings.luau +92 -0
- package/out/internal/data/record-declarations.d.ts +1 -0
- package/out/internal/data/record-declarations.luau +140 -0
- package/out/internal/data/records.d.ts +1 -0
- package/out/internal/data/records.luau +400 -0
- package/out/internal/data/runtime.d.ts +1 -0
- package/out/internal/data/runtime.luau +918 -0
- package/out/internal/data/scheduler.d.ts +1 -0
- package/out/internal/data/scheduler.luau +507 -0
- package/out/internal/data/session.d.ts +1 -0
- package/out/internal/data/session.luau +234 -0
- package/out/internal/data/shutdown.d.ts +1 -0
- package/out/internal/data/shutdown.luau +91 -0
- package/out/internal/data/waiters.d.ts +1 -0
- package/out/internal/data/waiters.luau +65 -0
- package/out/internal/dense-list.d.ts +1 -0
- package/out/internal/dense-list.luau +155 -0
- package/out/internal/diagnostics.d.ts +1 -0
- package/out/internal/diagnostics.luau +29 -0
- package/out/internal/hooks.d.ts +1 -0
- package/out/internal/hooks.luau +53 -0
- package/out/internal/implementers.d.ts +1 -0
- package/out/internal/implementers.luau +119 -0
- package/out/internal/lifecycle.d.ts +1 -0
- package/out/internal/lifecycle.luau +912 -0
- package/out/internal/log-output.d.ts +1 -0
- package/out/internal/log-output.luau +106 -0
- package/out/internal/network/catalog.d.ts +26 -0
- package/out/internal/network/catalog.luau +182 -0
- package/out/internal/network/claims.d.ts +1 -0
- package/out/internal/network/claims.luau +154 -0
- package/out/internal/network/client-session.d.ts +1 -0
- package/out/internal/network/client-session.luau +403 -0
- package/out/internal/network/codec.d.ts +63 -0
- package/out/internal/network/codec.luau +1183 -0
- package/out/internal/network/envelope.d.ts +1 -0
- package/out/internal/network/envelope.luau +247 -0
- package/out/internal/network/limits.d.ts +26 -0
- package/out/internal/network/limits.luau +55 -0
- package/out/internal/network/port.d.ts +1 -0
- package/out/internal/network/port.luau +19 -0
- package/out/internal/network/roblox-network-port.d.ts +1 -0
- package/out/internal/network/roblox-network-port.luau +105 -0
- package/out/internal/network/schema.d.ts +72 -0
- package/out/internal/network/schema.luau +386 -0
- package/out/internal/network/server-session.d.ts +1 -0
- package/out/internal/network/server-session.luau +393 -0
- package/out/internal/network/session.d.ts +1 -0
- package/out/internal/network/session.luau +266 -0
- package/out/internal/port.d.ts +1 -0
- package/out/internal/port.luau +12 -0
- package/out/internal/reactive/context.d.ts +1 -0
- package/out/internal/reactive/context.luau +149 -0
- package/out/internal/reactive/flush.d.ts +1 -0
- package/out/internal/reactive/flush.luau +355 -0
- package/out/internal/reactive/graph.d.ts +1 -0
- package/out/internal/reactive/graph.luau +626 -0
- package/out/internal/reactive/limits.d.ts +1 -0
- package/out/internal/reactive/limits.luau +54 -0
- package/out/internal/reactive/ownership.d.ts +1 -0
- package/out/internal/reactive/ownership.luau +626 -0
- package/out/internal/registry.d.ts +1 -0
- package/out/internal/registry.luau +455 -0
- package/out/internal/roblox-port.d.ts +1 -0
- package/out/internal/roblox-port.luau +117 -0
- package/out/internal/runner.d.ts +1 -0
- package/out/internal/runner.luau +86 -0
- package/out/internal/scheduler.d.ts +1 -0
- package/out/internal/scheduler.luau +207 -0
- package/out/internal/state.d.ts +1 -0
- package/out/internal/state.luau +41 -0
- package/out/internal/sync/client-sync.d.ts +1 -0
- package/out/internal/sync/client-sync.luau +157 -0
- package/out/internal/sync/declarations.d.ts +1 -0
- package/out/internal/sync/declarations.luau +276 -0
- package/out/internal/sync/frame.d.ts +1 -0
- package/out/internal/sync/frame.luau +91 -0
- package/out/internal/sync/server-sync.d.ts +1 -0
- package/out/internal/sync/server-sync.luau +502 -0
- package/out/internal/sync/values.d.ts +1 -0
- package/out/internal/sync/values.luau +930 -0
- package/out/log-level.d.ts +7 -0
- package/out/log-level.luau +21 -0
- package/out/logging.d.ts +34 -0
- package/out/logging.luau +233 -0
- package/out/network.d.ts +66 -0
- package/out/network.luau +24 -0
- package/out/reactive.d.ts +76 -0
- package/out/reactive.luau +136 -0
- package/out/replicated.d.ts +38 -0
- package/out/replicated.luau +45 -0
- package/out/server/data.d.ts +54 -0
- package/out/server/data.luau +44 -0
- package/out/server/index.d.ts +18 -0
- package/out/server/init.luau +62 -0
- package/out/server/publish.d.ts +20 -0
- package/out/server/publish.luau +24 -0
- package/out/subsystem.d.ts +4 -0
- package/out/subsystem.luau +30 -0
- package/out/vide/index.d.ts +7 -0
- package/out/vide/init.luau +50 -0
- package/package.json +52 -5
- package/server/package.json +4 -0
- package/transformer/data.cjs +72 -0
- package/transformer/declarations.cjs +153 -0
- package/transformer/diagnostics.cjs +19 -0
- package/transformer/index.js +741 -0
- package/transformer/network.cjs +961 -0
- package/transformer/type-id.cjs +80 -0
- package/vide/package.json +4 -0
- package/README.md +0 -3
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local runtimeDiagnostic = TS.import(script, script.Parent, "diagnostics").runtimeDiagnostic
|
|
4
|
+
local Subsystem = TS.import(script, script.Parent.Parent, "subsystem").Subsystem
|
|
5
|
+
local CrucibleBehaviour = TS.import(script, script.Parent.Parent, "crucible-behaviour").CrucibleBehaviour
|
|
6
|
+
local _binding = TS.import(script, script.Parent, "binding")
|
|
7
|
+
local construct = _binding.construct
|
|
8
|
+
local forget = _binding.forget
|
|
9
|
+
local reconcile = _binding.reconcile
|
|
10
|
+
local useEngine = _binding.useEngine
|
|
11
|
+
local watch = _binding.watch
|
|
12
|
+
local _hooks = TS.import(script, script.Parent, "hooks")
|
|
13
|
+
local hooks = _hooks.hooks
|
|
14
|
+
local lifecycleHooks = _hooks.lifecycleHooks
|
|
15
|
+
local shutdownHooks = _hooks.shutdownHooks
|
|
16
|
+
local useImplementerPort = TS.import(script, script.Parent, "implementers").useImplementerPort
|
|
17
|
+
local _lifecycle = TS.import(script, script.Parent, "lifecycle")
|
|
18
|
+
local admit = _lifecycle.admit
|
|
19
|
+
local drain = _lifecycle.drain
|
|
20
|
+
local hasEnded = _lifecycle.hasEnded
|
|
21
|
+
local request = _lifecycle.request
|
|
22
|
+
local track = _lifecycle.track
|
|
23
|
+
local useEffects = _lifecycle.useEffects
|
|
24
|
+
local _registry = TS.import(script, script.Parent, "registry")
|
|
25
|
+
local records = _registry.records
|
|
26
|
+
local seal = _registry.seal
|
|
27
|
+
local robloxPort = TS.import(script, script.Parent, "roblox-port").robloxPort
|
|
28
|
+
local Scheduler = TS.import(script, script.Parent, "scheduler").Scheduler
|
|
29
|
+
local _flush = TS.import(script, script.Parent, "reactive", "flush")
|
|
30
|
+
local holdBarrier = _flush.holdBarrier
|
|
31
|
+
local releaseBarrier = _flush.releaseBarrier
|
|
32
|
+
local useReactivePort = _flush.useReactivePort
|
|
33
|
+
local endInterval = TS.import(script, script.Parent, "reactive", "ownership").endInterval
|
|
34
|
+
local _declarations = TS.import(script, script.Parent, "sync", "declarations")
|
|
35
|
+
local rollbackDeclarations = _declarations.rollbackDeclarations
|
|
36
|
+
local sealDeclarations = _declarations.sealDeclarations
|
|
37
|
+
--* @internal
|
|
38
|
+
local BOOT_CLASSES = { Subsystem, CrucibleBehaviour }
|
|
39
|
+
--* @internal
|
|
40
|
+
--* @internal
|
|
41
|
+
local PATTERN_PREFIX = "crucible-path:"
|
|
42
|
+
--* @internal
|
|
43
|
+
local SHUTDOWN_DEADLINE_SECONDS = 25
|
|
44
|
+
--* @internal
|
|
45
|
+
local SHUTDOWN_TIMEOUT_SECONDS = 28
|
|
46
|
+
local clock
|
|
47
|
+
local sweep
|
|
48
|
+
--* @internal
|
|
49
|
+
--* @internal The one monotonic clock, core's and data's (data rules 25, 105).
|
|
50
|
+
local function bootClock()
|
|
51
|
+
return (clock or os.clock)()
|
|
52
|
+
end
|
|
53
|
+
--* @internal Undefined until the sweep has begun.
|
|
54
|
+
local function shutdownProgress(subsystem)
|
|
55
|
+
if sweep == nil then
|
|
56
|
+
return nil
|
|
57
|
+
end
|
|
58
|
+
local pending = 0
|
|
59
|
+
local notStarted = 0
|
|
60
|
+
for _, record in sweep.order do
|
|
61
|
+
local _condition = sweep.finished[record] ~= nil
|
|
62
|
+
if not _condition then
|
|
63
|
+
local _result = record.state
|
|
64
|
+
if _result ~= nil then
|
|
65
|
+
_result = _result.object
|
|
66
|
+
end
|
|
67
|
+
_condition = _result == subsystem
|
|
68
|
+
end
|
|
69
|
+
if _condition then
|
|
70
|
+
continue
|
|
71
|
+
end
|
|
72
|
+
pending += 1
|
|
73
|
+
if not (sweep.started[record] ~= nil) then
|
|
74
|
+
notStarted += 1
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
return {
|
|
78
|
+
startedAt = sweep.startTime,
|
|
79
|
+
forceStartAt = sweep.startTime + SHUTDOWN_DEADLINE_SECONDS,
|
|
80
|
+
deadline = sweep.startTime + SHUTDOWN_TIMEOUT_SECONDS,
|
|
81
|
+
pending = pending,
|
|
82
|
+
notStarted = notStarted,
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
--* @internal
|
|
86
|
+
local function parsePattern(pattern)
|
|
87
|
+
local _pattern = pattern
|
|
88
|
+
local _arg1 = #PATTERN_PREFIX
|
|
89
|
+
if string.sub(_pattern, 1, _arg1) ~= PATTERN_PREFIX then
|
|
90
|
+
error(`Crucible load needs the transformer: {pattern}`)
|
|
91
|
+
end
|
|
92
|
+
local _pattern_1 = pattern
|
|
93
|
+
local _arg0 = #PATTERN_PREFIX + 1
|
|
94
|
+
local segments = string.split(string.sub(_pattern_1, _arg0), "/")
|
|
95
|
+
-- ▼ ReadonlyArray.some ▼
|
|
96
|
+
local _result = false
|
|
97
|
+
local _callback = function(s)
|
|
98
|
+
return s == "" or s == "." or s == ".."
|
|
99
|
+
end
|
|
100
|
+
for _k, _v in segments do
|
|
101
|
+
if _callback(_v, _k - 1, segments) then
|
|
102
|
+
_result = true
|
|
103
|
+
break
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
-- ▲ ReadonlyArray.some ▲
|
|
107
|
+
if _result then
|
|
108
|
+
error(`Invalid Crucible load pattern: {pattern}`)
|
|
109
|
+
end
|
|
110
|
+
return segments
|
|
111
|
+
end
|
|
112
|
+
local function matches(name, pattern)
|
|
113
|
+
local open = string.find(pattern, "{", 1, true)
|
|
114
|
+
if open ~= nil then
|
|
115
|
+
local close = string.find(pattern, "}", open, true)
|
|
116
|
+
if close == nil then
|
|
117
|
+
error(`Invalid Crucible name pattern: {pattern}`)
|
|
118
|
+
end
|
|
119
|
+
local _pattern = pattern
|
|
120
|
+
local _arg0 = open + 1
|
|
121
|
+
local _arg1 = close - 1
|
|
122
|
+
local _exp = string.split(string.sub(_pattern, _arg0, _arg1), ",")
|
|
123
|
+
-- ▼ ReadonlyArray.some ▼
|
|
124
|
+
local _result = false
|
|
125
|
+
local _callback = function(part)
|
|
126
|
+
local _exp_1 = name
|
|
127
|
+
local _pattern_1 = pattern
|
|
128
|
+
local _arg1_1 = open - 1
|
|
129
|
+
local _exp_2 = string.sub(_pattern_1, 1, _arg1_1) .. part
|
|
130
|
+
local _pattern_2 = pattern
|
|
131
|
+
local _arg0_1 = close + 1
|
|
132
|
+
return matches(_exp_1, _exp_2 .. string.sub(_pattern_2, _arg0_1))
|
|
133
|
+
end
|
|
134
|
+
for _k, _v in _exp do
|
|
135
|
+
if _callback(_v, _k - 1, _exp) then
|
|
136
|
+
_result = true
|
|
137
|
+
break
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
-- ▲ ReadonlyArray.some ▲
|
|
141
|
+
return _result
|
|
142
|
+
end
|
|
143
|
+
local star = string.find(pattern, "*", 1, true)
|
|
144
|
+
if star == nil then
|
|
145
|
+
return name == pattern
|
|
146
|
+
end
|
|
147
|
+
local _pattern = pattern
|
|
148
|
+
local _arg1 = star - 1
|
|
149
|
+
local prefix = string.sub(_pattern, 1, _arg1)
|
|
150
|
+
local _name = name
|
|
151
|
+
local _arg1_1 = #prefix
|
|
152
|
+
if string.sub(_name, 1, _arg1_1) ~= prefix then
|
|
153
|
+
return false
|
|
154
|
+
end
|
|
155
|
+
for i = #prefix, #name do
|
|
156
|
+
local _name_1 = name
|
|
157
|
+
local _arg0 = i + 1
|
|
158
|
+
local _exp = string.sub(_name_1, _arg0)
|
|
159
|
+
local _pattern_1 = pattern
|
|
160
|
+
local _arg0_1 = star + 1
|
|
161
|
+
if matches(_exp, string.sub(_pattern_1, _arg0_1)) then
|
|
162
|
+
return true
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
return false
|
|
166
|
+
end
|
|
167
|
+
--* @internal
|
|
168
|
+
local function load(patterns)
|
|
169
|
+
local found = {}
|
|
170
|
+
local function walk(node, segments, index)
|
|
171
|
+
if index == #segments then
|
|
172
|
+
if node:IsA("ModuleScript") then
|
|
173
|
+
local _node = node
|
|
174
|
+
found[_node] = true
|
|
175
|
+
end
|
|
176
|
+
return nil
|
|
177
|
+
end
|
|
178
|
+
local segment = segments[index + 1]
|
|
179
|
+
if segment == "**" then
|
|
180
|
+
walk(node, segments, index + 1)
|
|
181
|
+
end
|
|
182
|
+
for _, child in node:GetChildren() do
|
|
183
|
+
if segment == "**" then
|
|
184
|
+
walk(child, segments, index)
|
|
185
|
+
elseif matches(child.Name, segment) then
|
|
186
|
+
walk(child, segments, index + 1)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
for _, pattern in patterns do
|
|
191
|
+
local segments = parsePattern(pattern)
|
|
192
|
+
walk(game:GetService(segments[1]), segments, 1)
|
|
193
|
+
end
|
|
194
|
+
local _array = {}
|
|
195
|
+
local _length = #_array
|
|
196
|
+
for _v in found do
|
|
197
|
+
_length += 1
|
|
198
|
+
_array[_length] = _v
|
|
199
|
+
end
|
|
200
|
+
local modules = _array
|
|
201
|
+
table.sort(modules, function(a, b)
|
|
202
|
+
return a:GetFullName() < b:GetFullName()
|
|
203
|
+
end)
|
|
204
|
+
for _, module in modules do
|
|
205
|
+
require(module)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
local HOOK_NAMES = { "constructor", "awake", "onEnable", "start", "onDisable", "onDestroy", "a frame hook", "accepts", "an All<T> callback", "settle", "cancel", "internal" }
|
|
209
|
+
local function where(port, s)
|
|
210
|
+
local id = (s.record).id
|
|
211
|
+
return if s.instance == nil then id else `{id} on {port.describe(s.instance)}`
|
|
212
|
+
end
|
|
213
|
+
local function describeFault(port, s)
|
|
214
|
+
local fault = s.fault
|
|
215
|
+
local message = `{where(port, s)} faulted in {HOOK_NAMES[fault.hook + 1]}: {tostring(fault.error)}`
|
|
216
|
+
for _, later in fault.cleanup do
|
|
217
|
+
message ..= `\n then {HOOK_NAMES[later.hook + 1]} failed: {tostring(later.error)}`
|
|
218
|
+
end
|
|
219
|
+
return message
|
|
220
|
+
end
|
|
221
|
+
local function hookCaller(s, hook)
|
|
222
|
+
if hook == 1 then
|
|
223
|
+
return function(s)
|
|
224
|
+
return hooks().awake(s.object, 0)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
if s.record.kind ~= 1 then
|
|
228
|
+
return nil
|
|
229
|
+
end
|
|
230
|
+
if hook == 2 then
|
|
231
|
+
return function(s)
|
|
232
|
+
return lifecycleHooks().onEnable(s.object, 0)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
if hook == 4 then
|
|
236
|
+
return function(s)
|
|
237
|
+
return lifecycleHooks().onDisable(s.object, 0)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
if hook == 5 then
|
|
241
|
+
return function(s)
|
|
242
|
+
return lifecycleHooks().onDestroy(s.object, 0)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
return nil
|
|
246
|
+
end
|
|
247
|
+
local function shutdown(port, order)
|
|
248
|
+
local started = {}
|
|
249
|
+
local finished = {}
|
|
250
|
+
local dependents = {}
|
|
251
|
+
for _, record in order do
|
|
252
|
+
dependents[record] = {}
|
|
253
|
+
end
|
|
254
|
+
for _, record in order do
|
|
255
|
+
for _1, dep in record.resolved do
|
|
256
|
+
if not dep.all then
|
|
257
|
+
local _record = dep.record
|
|
258
|
+
local _exp = dependents[_record]
|
|
259
|
+
table.insert(_exp, record)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
local startTime = port.clock()
|
|
264
|
+
sweep = {
|
|
265
|
+
startTime = startTime,
|
|
266
|
+
order = order,
|
|
267
|
+
started = started,
|
|
268
|
+
finished = finished,
|
|
269
|
+
}
|
|
270
|
+
while true do
|
|
271
|
+
-- ▼ ReadonlySet.size ▼
|
|
272
|
+
local _size = 0
|
|
273
|
+
for _ in finished do
|
|
274
|
+
_size += 1
|
|
275
|
+
end
|
|
276
|
+
-- ▲ ReadonlySet.size ▲
|
|
277
|
+
if not (_size < #order) then
|
|
278
|
+
break
|
|
279
|
+
end
|
|
280
|
+
local expired = port.clock() - startTime >= SHUTDOWN_DEADLINE_SECONDS
|
|
281
|
+
for _, record in order do
|
|
282
|
+
local _condition = started[record] ~= nil
|
|
283
|
+
if not _condition then
|
|
284
|
+
local _condition_1 = not expired
|
|
285
|
+
if _condition_1 then
|
|
286
|
+
local _exp = dependents[record]
|
|
287
|
+
-- ▼ ReadonlyArray.every ▼
|
|
288
|
+
local _result = true
|
|
289
|
+
local _callback = function(r)
|
|
290
|
+
local _r = r
|
|
291
|
+
return finished[_r] ~= nil
|
|
292
|
+
end
|
|
293
|
+
for _k, _v in _exp do
|
|
294
|
+
if not _callback(_v, _k - 1, _exp) then
|
|
295
|
+
_result = false
|
|
296
|
+
break
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
-- ▲ ReadonlyArray.every ▲
|
|
300
|
+
_condition_1 = not _result
|
|
301
|
+
end
|
|
302
|
+
_condition = _condition_1
|
|
303
|
+
end
|
|
304
|
+
if _condition then
|
|
305
|
+
continue
|
|
306
|
+
end
|
|
307
|
+
started[record] = true
|
|
308
|
+
port.spawn(function()
|
|
309
|
+
local _object = record.state
|
|
310
|
+
if _object ~= nil then
|
|
311
|
+
_object = _object.object
|
|
312
|
+
end
|
|
313
|
+
local object = _object
|
|
314
|
+
if object ~= nil then
|
|
315
|
+
local ok, err = xpcall(function()
|
|
316
|
+
return shutdownHooks().onShutdown(object)
|
|
317
|
+
end, function(err)
|
|
318
|
+
return debug.traceback(tostring(err), 2)
|
|
319
|
+
end)
|
|
320
|
+
if not ok then
|
|
321
|
+
runtimeDiagnostic("error", `{record.id} onShutdown failed: {err}`)
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
finished[record] = true
|
|
325
|
+
end)
|
|
326
|
+
end
|
|
327
|
+
if port.clock() - startTime >= SHUTDOWN_TIMEOUT_SECONDS then
|
|
328
|
+
return nil
|
|
329
|
+
end
|
|
330
|
+
-- ▼ ReadonlySet.size ▼
|
|
331
|
+
local _size_1 = 0
|
|
332
|
+
for _ in finished do
|
|
333
|
+
_size_1 += 1
|
|
334
|
+
end
|
|
335
|
+
-- ▲ ReadonlySet.size ▲
|
|
336
|
+
if _size_1 < #order then
|
|
337
|
+
port.wait()
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
--* @internal
|
|
342
|
+
local function ignite(port, side, options)
|
|
343
|
+
clock = port.clock
|
|
344
|
+
sweep = nil
|
|
345
|
+
local singletons = seal({
|
|
346
|
+
renders = side.renders,
|
|
347
|
+
})
|
|
348
|
+
local frame = hooks().frame
|
|
349
|
+
local _exp = port
|
|
350
|
+
local _object = {}
|
|
351
|
+
local _left = "fixedRate"
|
|
352
|
+
local _condition = options.fixedRate
|
|
353
|
+
if _condition == nil then
|
|
354
|
+
_condition = 60
|
|
355
|
+
end
|
|
356
|
+
_object[_left] = _condition
|
|
357
|
+
_object.renders = side.renders
|
|
358
|
+
local scheduler = Scheduler.new(_exp, _object, {
|
|
359
|
+
[0] = function(o, dt)
|
|
360
|
+
return frame[0](o, dt)
|
|
361
|
+
end,
|
|
362
|
+
[1] = function(o, dt)
|
|
363
|
+
return frame[1](o, dt)
|
|
364
|
+
end,
|
|
365
|
+
[2] = function(o, dt)
|
|
366
|
+
return frame[2](o, dt)
|
|
367
|
+
end,
|
|
368
|
+
[3] = function(o, dt)
|
|
369
|
+
return frame[3](o, dt)
|
|
370
|
+
end,
|
|
371
|
+
})
|
|
372
|
+
local owned = {}
|
|
373
|
+
local stage = "booting"
|
|
374
|
+
local failure
|
|
375
|
+
local stop = function() end
|
|
376
|
+
local function reject(message)
|
|
377
|
+
if stage ~= "booting" then
|
|
378
|
+
return nil
|
|
379
|
+
end
|
|
380
|
+
failure = message
|
|
381
|
+
stage = "rollback"
|
|
382
|
+
stop()
|
|
383
|
+
for state in owned do
|
|
384
|
+
request(state, 2)
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
useEngine(port)
|
|
388
|
+
holdBarrier()
|
|
389
|
+
useReactivePort(port)
|
|
390
|
+
useImplementerPort(port)
|
|
391
|
+
useEffects({
|
|
392
|
+
construct = function(s)
|
|
393
|
+
if stage == "booting" then
|
|
394
|
+
local _s = s
|
|
395
|
+
owned[_s] = true
|
|
396
|
+
end
|
|
397
|
+
return construct(s)
|
|
398
|
+
end,
|
|
399
|
+
hook = hookCaller,
|
|
400
|
+
start = function(s)
|
|
401
|
+
return hooks().start(s.object, 0)
|
|
402
|
+
end,
|
|
403
|
+
join = function(s)
|
|
404
|
+
for _, set in (s.record).memberOf do
|
|
405
|
+
set:join(s.object)
|
|
406
|
+
end
|
|
407
|
+
end,
|
|
408
|
+
leave = function(s)
|
|
409
|
+
for _, set in (s.record).memberOf do
|
|
410
|
+
set:leave(s.object)
|
|
411
|
+
end
|
|
412
|
+
end,
|
|
413
|
+
tick = function(s)
|
|
414
|
+
return scheduler:add(s)
|
|
415
|
+
end,
|
|
416
|
+
untick = function(s)
|
|
417
|
+
return scheduler:remove(s)
|
|
418
|
+
end,
|
|
419
|
+
reconcile = function()
|
|
420
|
+
if stage == "rollback" then
|
|
421
|
+
return {}
|
|
422
|
+
end
|
|
423
|
+
local created = reconcile()
|
|
424
|
+
if stage == "booting" then
|
|
425
|
+
for _, s in created do
|
|
426
|
+
owned[s] = true
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
return created
|
|
430
|
+
end,
|
|
431
|
+
ended = function(s)
|
|
432
|
+
forget(s)
|
|
433
|
+
if s.fault == nil then
|
|
434
|
+
return nil
|
|
435
|
+
end
|
|
436
|
+
local message = describeFault(port, s)
|
|
437
|
+
runtimeDiagnostic("error", message)
|
|
438
|
+
if s.record.kind == 0 then
|
|
439
|
+
reject(message)
|
|
440
|
+
end
|
|
441
|
+
end,
|
|
442
|
+
defer = port.defer,
|
|
443
|
+
cancel = port.cancel,
|
|
444
|
+
failed = function(message)
|
|
445
|
+
runtimeDiagnostic("error", message)
|
|
446
|
+
reject(message)
|
|
447
|
+
end,
|
|
448
|
+
diagnose = function(s, hook, err)
|
|
449
|
+
return runtimeDiagnostic("error", `{where(port, s)} {HOOK_NAMES[hook + 1]} failed: {tostring(err)}`)
|
|
450
|
+
end,
|
|
451
|
+
disabled = endInterval,
|
|
452
|
+
})
|
|
453
|
+
local ok, err = pcall(function()
|
|
454
|
+
local _exp_1 = records()
|
|
455
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
456
|
+
local _newValue = {}
|
|
457
|
+
local _callback = function(r)
|
|
458
|
+
return r.kind == 1
|
|
459
|
+
end
|
|
460
|
+
local _length = 0
|
|
461
|
+
for _k, _v in _exp_1 do
|
|
462
|
+
if _callback(_v, _k - 1, _exp_1) == true then
|
|
463
|
+
_length += 1
|
|
464
|
+
_newValue[_length] = _v
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
468
|
+
stop = watch(_newValue)
|
|
469
|
+
-- ▼ ReadonlyArray.map ▼
|
|
470
|
+
local _newValue_1 = table.create(#singletons)
|
|
471
|
+
local _callback_1 = function(r)
|
|
472
|
+
local s = track(r)
|
|
473
|
+
r.state = s
|
|
474
|
+
owned[s] = true
|
|
475
|
+
return s
|
|
476
|
+
end
|
|
477
|
+
for _k, _v in singletons do
|
|
478
|
+
_newValue_1[_k] = _callback_1(_v, _k - 1, singletons)
|
|
479
|
+
end
|
|
480
|
+
-- ▲ ReadonlyArray.map ▲
|
|
481
|
+
local initial = _newValue_1
|
|
482
|
+
admit(initial)
|
|
483
|
+
drain()
|
|
484
|
+
end)
|
|
485
|
+
if not ok then
|
|
486
|
+
reject(tostring(err))
|
|
487
|
+
end
|
|
488
|
+
if failure == nil then
|
|
489
|
+
local unbooted = nil
|
|
490
|
+
local finalized, finalizeErr = pcall(function()
|
|
491
|
+
-- Roblox cannot unbind BindToClose, so the callback checks that this boot committed.
|
|
492
|
+
if side.name == "server" then
|
|
493
|
+
port.bindToClose(function()
|
|
494
|
+
if stage ~= "committed" then
|
|
495
|
+
return nil
|
|
496
|
+
end
|
|
497
|
+
shutdown(port, singletons)
|
|
498
|
+
side.network:close()
|
|
499
|
+
end)
|
|
500
|
+
end
|
|
501
|
+
unbooted = side.booted()
|
|
502
|
+
if side.name == "client" then
|
|
503
|
+
sealDeclarations()
|
|
504
|
+
end
|
|
505
|
+
side.network:commit()
|
|
506
|
+
end)
|
|
507
|
+
if not finalized then
|
|
508
|
+
local undo = unbooted
|
|
509
|
+
if undo ~= nil then
|
|
510
|
+
local undone, undoErr = pcall(undo)
|
|
511
|
+
if not undone then
|
|
512
|
+
runtimeDiagnostic("error", `Crucible: undoing booted failed: {tostring(undoErr)}`)
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
reject(`boot finalization failed: {tostring(finalizeErr)}`)
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
if failure ~= nil then
|
|
519
|
+
for s in owned do
|
|
520
|
+
if not hasEnded(s) then
|
|
521
|
+
request(s, 2)
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
drain()
|
|
525
|
+
table.clear(owned)
|
|
526
|
+
releaseBarrier()
|
|
527
|
+
error(`Crucible boot failed: {failure}`, 0)
|
|
528
|
+
end
|
|
529
|
+
stage = "committed"
|
|
530
|
+
table.clear(owned)
|
|
531
|
+
releaseBarrier()
|
|
532
|
+
end
|
|
533
|
+
--* @internal
|
|
534
|
+
local function boot(side, options)
|
|
535
|
+
local ok, err = pcall(function()
|
|
536
|
+
side.network:open()
|
|
537
|
+
load(options.load)
|
|
538
|
+
side.network:loaded()
|
|
539
|
+
if side.name == "server" then
|
|
540
|
+
sealDeclarations()
|
|
541
|
+
end
|
|
542
|
+
ignite(robloxPort(), side, options)
|
|
543
|
+
end)
|
|
544
|
+
if ok then
|
|
545
|
+
return nil
|
|
546
|
+
end
|
|
547
|
+
side.network:close()
|
|
548
|
+
rollbackDeclarations()
|
|
549
|
+
error(err, 0)
|
|
550
|
+
end
|
|
551
|
+
return {
|
|
552
|
+
bootClock = bootClock,
|
|
553
|
+
shutdownProgress = shutdownProgress,
|
|
554
|
+
parsePattern = parsePattern,
|
|
555
|
+
load = load,
|
|
556
|
+
ignite = ignite,
|
|
557
|
+
boot = boot,
|
|
558
|
+
BOOT_CLASSES = BOOT_CLASSES,
|
|
559
|
+
PATTERN_PREFIX = PATTERN_PREFIX,
|
|
560
|
+
SHUTDOWN_DEADLINE_SECONDS = SHUTDOWN_DEADLINE_SECONDS,
|
|
561
|
+
SHUTDOWN_TIMEOUT_SECONDS = SHUTDOWN_TIMEOUT_SECONDS,
|
|
562
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const MAX_CONFIG_DECLARATIONS = 1000;
|
|
2
|
+
export declare const CONFIG_NAME_MAX_BYTES = 64;
|
|
3
|
+
export declare const CONFIG_VALUE_MAX_BYTES = 100000;
|
|
4
|
+
export declare const CONFIG_ADMISSION_VISITS = 100000;
|
|
5
|
+
export declare const CONFIG_REQUEST_CONCURRENCY = 4;
|
|
6
|
+
export declare const CONFIG_FETCH_RETRY_BASE_SECONDS = 1;
|
|
7
|
+
export declare const CONFIG_FETCH_RETRY_CAP_SECONDS = 30;
|
|
8
|
+
export declare const CONFIG_REFRESH_TIMEOUT_SECONDS = 10;
|
|
9
|
+
export declare const CONFIG_VALUE_DEPTH = 28;
|
|
10
|
+
export declare const CONFIG_STRING_MAX_BYTES = 65536;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local MAX_CONFIG_DECLARATIONS = 1_000
|
|
3
|
+
local CONFIG_NAME_MAX_BYTES = 64
|
|
4
|
+
local CONFIG_VALUE_MAX_BYTES = 100_000
|
|
5
|
+
local CONFIG_ADMISSION_VISITS = 100_000
|
|
6
|
+
local CONFIG_REQUEST_CONCURRENCY = 4
|
|
7
|
+
local CONFIG_FETCH_RETRY_BASE_SECONDS = 1
|
|
8
|
+
local CONFIG_FETCH_RETRY_CAP_SECONDS = 30
|
|
9
|
+
local CONFIG_REFRESH_TIMEOUT_SECONDS = 10
|
|
10
|
+
-- Rule 97 admits configs by rule 76's walk, whose depth and string bounds are data's PERSIST_DEPTH and
|
|
11
|
+
-- PERSIST_STRING_BYTES. Data's limits module is not under configs yet, so the values are restated here.
|
|
12
|
+
local CONFIG_VALUE_DEPTH = 28
|
|
13
|
+
local CONFIG_STRING_MAX_BYTES = 65_536
|
|
14
|
+
return {
|
|
15
|
+
MAX_CONFIG_DECLARATIONS = MAX_CONFIG_DECLARATIONS,
|
|
16
|
+
CONFIG_NAME_MAX_BYTES = CONFIG_NAME_MAX_BYTES,
|
|
17
|
+
CONFIG_VALUE_MAX_BYTES = CONFIG_VALUE_MAX_BYTES,
|
|
18
|
+
CONFIG_ADMISSION_VISITS = CONFIG_ADMISSION_VISITS,
|
|
19
|
+
CONFIG_REQUEST_CONCURRENCY = CONFIG_REQUEST_CONCURRENCY,
|
|
20
|
+
CONFIG_FETCH_RETRY_BASE_SECONDS = CONFIG_FETCH_RETRY_BASE_SECONDS,
|
|
21
|
+
CONFIG_FETCH_RETRY_CAP_SECONDS = CONFIG_FETCH_RETRY_CAP_SECONDS,
|
|
22
|
+
CONFIG_REFRESH_TIMEOUT_SECONDS = CONFIG_REFRESH_TIMEOUT_SECONDS,
|
|
23
|
+
CONFIG_VALUE_DEPTH = CONFIG_VALUE_DEPTH,
|
|
24
|
+
CONFIG_STRING_MAX_BYTES = CONFIG_STRING_MAX_BYTES,
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Disconnect } from "../port";
|
|
2
|
+
export interface ConfigSnapshotPort {
|
|
3
|
+
/** `GetValue`: nil for a missing key. A JSON config may arrive as a table or as its text. */
|
|
4
|
+
readonly get: (key: string) => unknown;
|
|
5
|
+
/** `Refresh`. Yields and may throw. */
|
|
6
|
+
readonly refresh: () => void;
|
|
7
|
+
/** Unmeasured in Studio: whether this turns true without `UpdateAvailable`. Runtime treats the two as independent. */
|
|
8
|
+
readonly outdated: () => boolean;
|
|
9
|
+
/** `Error` is `LoadFailed`. */
|
|
10
|
+
readonly failed: () => boolean;
|
|
11
|
+
readonly onUpdateAvailable: (listener: () => void) => Disconnect;
|
|
12
|
+
}
|
|
13
|
+
/** What configs ask of the engine. Requests yield and may throw. */
|
|
14
|
+
export interface ConfigPort {
|
|
15
|
+
readonly global: () => ConfigSnapshotPort;
|
|
16
|
+
readonly forPlayer: (player: Player) => ConfigSnapshotPort;
|
|
17
|
+
readonly players: () => readonly Player[];
|
|
18
|
+
readonly onPlayerAdded: (listener: (player: Player) => void) => Disconnect;
|
|
19
|
+
readonly onPlayerRemoving: (listener: (player: Player) => void) => Disconnect;
|
|
20
|
+
readonly wait: (seconds: number) => void;
|
|
21
|
+
/** Uniform in [0, 1). */
|
|
22
|
+
readonly random: () => number;
|
|
23
|
+
readonly decodeJson: (text: string) => unknown;
|
|
24
|
+
/** The JSON text length of a decoded value. Throws for a value JSON cannot hold. */
|
|
25
|
+
readonly jsonBytes: (value: object) => number;
|
|
26
|
+
}
|
|
27
|
+
export declare function installConfigPort(value: ConfigPort): void;
|
|
28
|
+
export declare function configPort(): ConfigPort;
|
|
29
|
+
export declare function createRobloxConfigPort(): ConfigPort;
|