@trioforge/crucible 0.0.0-stage → 0.1.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/client/package.json +4 -0
  3. package/emit/package.json +4 -0
  4. package/out/all.d.ts +7 -0
  5. package/out/all.luau +2 -0
  6. package/out/attribute.d.ts +7 -0
  7. package/out/attribute.luau +7 -0
  8. package/out/client/index.d.ts +3 -0
  9. package/out/client/init.luau +20 -0
  10. package/out/crucible-behaviour.d.ts +16 -0
  11. package/out/crucible-behaviour.luau +78 -0
  12. package/out/crucible-object.d.ts +10 -0
  13. package/out/crucible-object.luau +69 -0
  14. package/out/emit/index.d.ts +41 -0
  15. package/out/emit/init.luau +85 -0
  16. package/out/index.d.ts +12 -0
  17. package/out/init.luau +11 -0
  18. package/out/inject.d.ts +1 -0
  19. package/out/inject.luau +7 -0
  20. package/out/internal/binding.d.ts +1 -0
  21. package/out/internal/binding.luau +610 -0
  22. package/out/internal/boot.d.ts +1 -0
  23. package/out/internal/boot.luau +463 -0
  24. package/out/internal/construction-claim.d.ts +1 -0
  25. package/out/internal/construction-claim.luau +26 -0
  26. package/out/internal/dense-list.d.ts +1 -0
  27. package/out/internal/dense-list.luau +155 -0
  28. package/out/internal/diagnostics.d.ts +1 -0
  29. package/out/internal/diagnostics.luau +29 -0
  30. package/out/internal/hooks.d.ts +1 -0
  31. package/out/internal/hooks.luau +53 -0
  32. package/out/internal/implementers.d.ts +1 -0
  33. package/out/internal/implementers.luau +119 -0
  34. package/out/internal/lifecycle.d.ts +1 -0
  35. package/out/internal/lifecycle.luau +867 -0
  36. package/out/internal/log-output.d.ts +1 -0
  37. package/out/internal/log-output.luau +106 -0
  38. package/out/internal/port.d.ts +1 -0
  39. package/out/internal/port.luau +12 -0
  40. package/out/internal/registry.d.ts +1 -0
  41. package/out/internal/registry.luau +446 -0
  42. package/out/internal/roblox-port.d.ts +1 -0
  43. package/out/internal/roblox-port.luau +117 -0
  44. package/out/internal/runner.d.ts +1 -0
  45. package/out/internal/runner.luau +86 -0
  46. package/out/internal/scheduler.d.ts +1 -0
  47. package/out/internal/scheduler.luau +207 -0
  48. package/out/internal/state.d.ts +1 -0
  49. package/out/internal/state.luau +41 -0
  50. package/out/log-level.d.ts +7 -0
  51. package/out/log-level.luau +21 -0
  52. package/out/logging.d.ts +34 -0
  53. package/out/logging.luau +233 -0
  54. package/out/server/index.d.ts +2 -0
  55. package/out/server/init.luau +16 -0
  56. package/out/subsystem.d.ts +4 -0
  57. package/out/subsystem.luau +30 -0
  58. package/package.json +41 -5
  59. package/server/package.json +4 -0
  60. package/transformer/diagnostics.cjs +19 -0
  61. package/transformer/index.js +715 -0
  62. package/transformer/type-id.cjs +80 -0
  63. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,106 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local LogLevel = TS.import(script, script.Parent.Parent, "log-level").LogLevel
4
+ --* @internal
5
+ local port
6
+ --* @internal
7
+ local function installLoggingPort(value)
8
+ local _arg0 = port == nil
9
+ assert(_arg0, "Logging port already selected")
10
+ port = value
11
+ end
12
+ --* @internal
13
+ local createRobloxLoggingPort
14
+ local function loggingPort()
15
+ if port == nil then
16
+ port = createRobloxLoggingPort()
17
+ end
18
+ return port
19
+ end
20
+ local function escape(text)
21
+ return (string.gsub((string.gsub(text, "{", "{{")), "}", "}}"))
22
+ end
23
+ --* @internal
24
+ function createRobloxLoggingPort()
25
+ local gameLogger
26
+ local crucibleLogger
27
+ local fallback = false
28
+ local studio = game:GetService("RunService"):IsStudio()
29
+ local function native(write, plain)
30
+ if not fallback then
31
+ local ok = pcall(function()
32
+ local service = game:GetService("LogService")
33
+ if gameLogger == nil then
34
+ gameLogger = service:GetLogger("Game")
35
+ end
36
+ if crucibleLogger == nil then
37
+ crucibleLogger = service:GetLogger("Crucible")
38
+ end
39
+ write()
40
+ end)
41
+ if ok then
42
+ return nil
43
+ end
44
+ fallback = true
45
+ end
46
+ plain()
47
+ end
48
+ return {
49
+ isStudio = function()
50
+ return studio
51
+ end,
52
+ now = function()
53
+ return os.clock()
54
+ end,
55
+ describeInstance = function(instance)
56
+ return instance:GetFullName()
57
+ end,
58
+ writeGame = function(record)
59
+ local text = `[{record.source}] {record.message}`
60
+ if record.level == LogLevel.Error then
61
+ task.spawn(function()
62
+ local _condition = record.traceback
63
+ if _condition == nil then
64
+ _condition = ""
65
+ end
66
+ return error(`{text}\n{_condition}`, 0)
67
+ end)
68
+ return nil
69
+ end
70
+ native(function()
71
+ local logger = gameLogger
72
+ if record.level == LogLevel.Debug then
73
+ logger:Output(escape(text), record.context)
74
+ elseif record.level == LogLevel.Info then
75
+ logger:Info(escape(text), record.context)
76
+ else
77
+ logger:Warn(escape(text), record.context)
78
+ end
79
+ end, function()
80
+ if record.level == LogLevel.Warning then
81
+ warn(text)
82
+ else
83
+ print(text)
84
+ end
85
+ end)
86
+ end,
87
+ writeInternal = function(level, message)
88
+ if level == "error" then
89
+ task.spawn(function()
90
+ return error(`[Crucible] {message}`, 0)
91
+ end)
92
+ else
93
+ native(function()
94
+ return crucibleLogger:Warn(escape(`[Crucible] {message}`), {})
95
+ end, function()
96
+ return warn(`[Crucible] {message}`)
97
+ end)
98
+ end
99
+ end,
100
+ }
101
+ end
102
+ return {
103
+ installLoggingPort = installLoggingPort,
104
+ loggingPort = loggingPort,
105
+ createRobloxLoggingPort = createRobloxLoggingPort,
106
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --* @internal Ends one engine subscription. Idempotent.
3
+ --* @internal The RunService events the scheduler connects. `BindToRenderStep` lanes have their own entry.
4
+ --[[
5
+ *
6
+ * @internal
7
+ * Everything the runtime asks of the engine. Coroutine functions are not here: they are the Luau language,
8
+ * identical in Roblox and Lune. The runner cancels a yielded worker with `task.cancel` itself, because the pool
9
+ * works before any port is installed.
10
+
11
+ ]]
12
+ return nil
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,446 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local hooks = TS.import(script, script.Parent, "hooks").hooks
4
+ local ImplementerSet = TS.import(script, script.Parent, "implementers").ImplementerSet
5
+ local drain = TS.import(script, script.Parent, "lifecycle").drain
6
+ --* @internal
7
+ --* @internal
8
+ --* @internal
9
+ --* @internal
10
+ --* @internal
11
+ --* @internal
12
+ --* @internal
13
+ --* @internal
14
+ --* @internal
15
+ --* @internal
16
+ --* @internal
17
+ --* @internal
18
+ local registered = {}
19
+ local byClass = {}
20
+ local duplicates = {}
21
+ local sets = {}
22
+ local sealed
23
+ --* @internal
24
+ local function define(klass, emitted)
25
+ if sealed ~= nil then
26
+ error(`Crucible: {emitted.id} registered after boot; it would never be constructed or bound`)
27
+ end
28
+ local id = emitted.id
29
+ -- ▼ ReadonlyArray.some ▼
30
+ local _result = false
31
+ local _callback = function(record)
32
+ return record.id == id
33
+ end
34
+ for _k, _v in registered do
35
+ if _callback(_v, _k - 1, registered) then
36
+ _result = true
37
+ break
38
+ end
39
+ end
40
+ -- ▲ ReadonlyArray.some ▲
41
+ if _result then
42
+ table.insert(duplicates, id)
43
+ end
44
+ local statics = klass
45
+ local _object = {
46
+ id = id,
47
+ klass = klass,
48
+ hooks = hooks().overrides(klass),
49
+ }
50
+ local _left = "deps"
51
+ local _exp = emitted.deps
52
+ -- ▼ ReadonlyArray.map ▼
53
+ local _newValue = table.create(#_exp)
54
+ local _callback_1 = function(dep)
55
+ local _dep = dep
56
+ return if type(_dep) == "string" then {
57
+ id = dep,
58
+ all = false,
59
+ } else {
60
+ id = dep.all,
61
+ all = true,
62
+ }
63
+ end
64
+ for _k, _v in _exp do
65
+ _newValue[_k] = _callback_1(_v, _k - 1, _exp)
66
+ end
67
+ -- ▲ ReadonlyArray.map ▲
68
+ _object[_left] = _newValue
69
+ local _left_1 = "provides"
70
+ local _array = { id }
71
+ local _length = #_array
72
+ local _exp_1 = emitted.provides
73
+ -- ▼ ReadonlyArray.map ▼
74
+ local _newValue_1 = table.create(#_exp_1)
75
+ local _callback_2 = function(provided)
76
+ return provided
77
+ end
78
+ for _k, _v in _exp_1 do
79
+ _newValue_1[_k] = _callback_2(_v, _k - 1, _exp_1)
80
+ end
81
+ -- ▲ ReadonlyArray.map ▲
82
+ table.move(_newValue_1, 1, #_newValue_1, _length + 1, _array)
83
+ _object[_left_1] = _array
84
+ _object.renderPriority = statics.renderPriority
85
+ _object.resolved = {}
86
+ _object.memberOf = {}
87
+ local base = _object
88
+ local record
89
+ if emitted.kind == "subsystem" then
90
+ local _object_1 = table.clone(base)
91
+ setmetatable(_object_1, nil)
92
+ _object_1.kind = 0
93
+ record = _object_1
94
+ else
95
+ local tag = emitted.tag
96
+ klass.tag = tag
97
+ local attributes
98
+ if emitted.attributes ~= nil then
99
+ attributes = {}
100
+ for name, check in pairs(emitted.attributes) do
101
+ attributes[name] = check
102
+ end
103
+ end
104
+ local _object_1 = table.clone(base)
105
+ setmetatable(_object_1, nil)
106
+ _object_1.kind = 1
107
+ _object_1.tag = tag
108
+ _object_1.instanceClasses = emitted.instance
109
+ _object_1.attributes = attributes
110
+ _object_1.bound = {}
111
+ _object_1.suppressed = {}
112
+ record = _object_1
113
+ end
114
+ local _record = record
115
+ table.insert(registered, _record)
116
+ local _klass = klass
117
+ local _record_1 = record
118
+ byClass[_klass] = _record_1
119
+ end
120
+ --* @internal
121
+ local function plan(records, side)
122
+ local problems = {}
123
+ local providers = {}
124
+ for _, record in records do
125
+ for _1, id in record.provides do
126
+ local list = providers[id]
127
+ if list == nil then
128
+ local _arg1 = { record }
129
+ providers[id] = _arg1
130
+ else
131
+ table.insert(list, record)
132
+ end
133
+ end
134
+ end
135
+ local single = {}
136
+ for _, record in records do
137
+ local edges = {}
138
+ for _1, dep in record.deps do
139
+ if dep.all then
140
+ continue
141
+ end
142
+ local _id = dep.id
143
+ local _condition = providers[_id]
144
+ if _condition == nil then
145
+ _condition = {}
146
+ end
147
+ local candidates = _condition
148
+ -- ▼ ReadonlyArray.filter ▼
149
+ local _newValue = {}
150
+ local _callback = function(candidate)
151
+ return candidate.kind == 0
152
+ end
153
+ local _length = 0
154
+ for _k, _v in candidates do
155
+ if _callback(_v, _k - 1, candidates) == true then
156
+ _length += 1
157
+ _newValue[_length] = _v
158
+ end
159
+ end
160
+ -- ▲ ReadonlyArray.filter ▲
161
+ local subsystems = _newValue
162
+ if #candidates == 0 then
163
+ local _arg0 = {
164
+ kind = "missing",
165
+ needer = record.id,
166
+ dep = dep.id,
167
+ }
168
+ table.insert(problems, _arg0)
169
+ elseif #subsystems == 0 then
170
+ local _arg0 = {
171
+ kind = "behaviour-dependency",
172
+ needer = record.id,
173
+ dep = dep.id,
174
+ }
175
+ table.insert(problems, _arg0)
176
+ elseif #candidates > 1 then
177
+ local _object = {
178
+ kind = "ambiguous",
179
+ needer = record.id,
180
+ dep = dep.id,
181
+ }
182
+ local _left = "providers"
183
+ -- ▼ ReadonlyArray.map ▼
184
+ local _newValue_1 = table.create(#candidates)
185
+ local _callback_1 = function(c)
186
+ return c.id
187
+ end
188
+ for _k, _v in candidates do
189
+ _newValue_1[_k] = _callback_1(_v, _k - 1, candidates)
190
+ end
191
+ -- ▲ ReadonlyArray.map ▲
192
+ _object[_left] = _newValue_1
193
+ table.insert(problems, _object)
194
+ else
195
+ local _arg0 = subsystems[1]
196
+ table.insert(edges, _arg0)
197
+ end
198
+ end
199
+ single[record] = edges
200
+ local renders = (bit32.band(record.hooks, (bit32.lshift(1, 0)))) ~= 0 or record.renderPriority ~= nil
201
+ if not side.renders and renders then
202
+ local _arg0 = {
203
+ kind = "render-on-server",
204
+ id = record.id,
205
+ priority = record.renderPriority,
206
+ }
207
+ table.insert(problems, _arg0)
208
+ end
209
+ end
210
+ local order = {}
211
+ local colour = {}
212
+ local path = {}
213
+ local visit
214
+ visit = function(record)
215
+ local _record = record
216
+ local seen = colour[_record]
217
+ if seen == "black" then
218
+ return nil
219
+ end
220
+ if seen == "grey" then
221
+ local _record_1 = record
222
+ local from = (table.find(path, _record_1) or 0) - 1
223
+ local cycle = {}
224
+ do
225
+ local i = from
226
+ local _shouldIncrement = false
227
+ while true do
228
+ if _shouldIncrement then
229
+ i += 1
230
+ else
231
+ _shouldIncrement = true
232
+ end
233
+ if not (i < #path) then
234
+ break
235
+ end
236
+ local _id = path[i + 1].id
237
+ table.insert(cycle, _id)
238
+ end
239
+ end
240
+ local _id = record.id
241
+ table.insert(cycle, _id)
242
+ local _arg0 = {
243
+ kind = "cycle",
244
+ path = cycle,
245
+ }
246
+ table.insert(problems, _arg0)
247
+ return nil
248
+ end
249
+ local _record_1 = record
250
+ colour[_record_1] = "grey"
251
+ local _record_2 = record
252
+ table.insert(path, _record_2)
253
+ local _record_3 = record
254
+ local _condition = single[_record_3]
255
+ if _condition == nil then
256
+ _condition = {}
257
+ end
258
+ for _, dep in _condition do
259
+ visit(dep)
260
+ end
261
+ path[#path] = nil
262
+ local _record_4 = record
263
+ colour[_record_4] = "black"
264
+ local _record_5 = record
265
+ table.insert(order, _record_5)
266
+ end
267
+ for _, record in records do
268
+ if record.kind == 0 then
269
+ visit(record)
270
+ end
271
+ end
272
+ if #problems > 0 then
273
+ return {
274
+ ok = false,
275
+ problems = problems,
276
+ }
277
+ end
278
+ return {
279
+ ok = true,
280
+ plan = {
281
+ providers = providers,
282
+ subsystemOrder = order,
283
+ },
284
+ }
285
+ end
286
+ local function describe(problem)
287
+ local _exp = problem.kind
288
+ repeat
289
+ if _exp == "duplicate" then
290
+ return `{problem.id} is registered twice`
291
+ end
292
+ if _exp == "missing" then
293
+ return `{problem.needer} needs {problem.dep}, which nothing provides`
294
+ end
295
+ if _exp == "ambiguous" then
296
+ return `{problem.needer} needs one {problem.dep}, but {table.concat(problem.providers, ", ")} all provide it`
297
+ end
298
+ if _exp == "behaviour-dependency" then
299
+ return `{problem.needer} needs {problem.dep}, which only behaviours provide; take All<T> or call X.get(instance)`
300
+ end
301
+ if _exp == "cycle" then
302
+ return `dependency cycle {table.concat(problem.path, " -> ")}; break it with All<T>`
303
+ end
304
+ if _exp == "render-on-server" then
305
+ return `{problem.id} renders but is loaded on the server`
306
+ end
307
+ until true
308
+ end
309
+ --* @internal
310
+ local setFor
311
+ local function seal(side)
312
+ if sealed ~= nil then
313
+ error("Crucible: boot already ran on this side")
314
+ end
315
+ local result = plan(registered, side)
316
+ local problems = {}
317
+ for _, id in duplicates do
318
+ local _arg0 = {
319
+ kind = "duplicate",
320
+ id = id,
321
+ }
322
+ table.insert(problems, _arg0)
323
+ end
324
+ if not result.ok then
325
+ for _, problem in result.problems do
326
+ table.insert(problems, problem)
327
+ end
328
+ end
329
+ if #problems > 0 then
330
+ -- ▼ ReadonlyArray.map ▼
331
+ local _newValue = table.create(#problems)
332
+ for _k, _v in problems do
333
+ _newValue[_k] = describe(_v, _k - 1, problems)
334
+ end
335
+ -- ▲ ReadonlyArray.map ▲
336
+ error(`Crucible could not boot:\n {table.concat(_newValue, "\n ")}`)
337
+ end
338
+ if not result.ok then
339
+ return {}
340
+ end
341
+ local _binding = result.plan
342
+ local providers = _binding.providers
343
+ local subsystemOrder = _binding.subsystemOrder
344
+ for _, record in registered do
345
+ local _exp = record.deps
346
+ -- ▼ ReadonlyArray.map ▼
347
+ local _newValue = table.create(#_exp)
348
+ local _callback = function(dep)
349
+ if dep.all then
350
+ return {
351
+ all = true,
352
+ set = setFor(dep.id),
353
+ }
354
+ end
355
+ local _object = {
356
+ all = false,
357
+ }
358
+ local _left = "record"
359
+ local _id = dep.id
360
+ local _condition = providers[_id]
361
+ if _condition == nil then
362
+ _condition = {}
363
+ end
364
+ _object[_left] = _condition[1]
365
+ return _object
366
+ end
367
+ for _k, _v in _exp do
368
+ _newValue[_k] = _callback(_v, _k - 1, _exp)
369
+ end
370
+ -- ▲ ReadonlyArray.map ▲
371
+ record.resolved = _newValue
372
+ local _exp_1 = record.provides
373
+ -- ▼ ReadonlyArray.map ▼
374
+ local _newValue_1 = table.create(#_exp_1)
375
+ for _k, _v in _exp_1 do
376
+ _newValue_1[_k] = setFor(_v, _k - 1, _exp_1)
377
+ end
378
+ -- ▲ ReadonlyArray.map ▲
379
+ record.memberOf = _newValue_1
380
+ end
381
+ sealed = result.plan
382
+ return subsystemOrder
383
+ end
384
+ --* @internal
385
+ local function records()
386
+ return registered
387
+ end
388
+ --* @internal
389
+ local function recordOf(klass)
390
+ local _klass = klass
391
+ return byClass[_klass]
392
+ end
393
+ --* @internal
394
+ local function resolveOne(id)
395
+ drain()
396
+ local plan = sealed or error(`inject<{id}>() called before boot`)
397
+ local _providers = plan.providers
398
+ local _id = id
399
+ local _condition = _providers[_id]
400
+ if _condition == nil then
401
+ _condition = {}
402
+ end
403
+ local candidates = _condition
404
+ local provider = candidates[1]
405
+ if #candidates ~= 1 or provider.kind ~= 0 then
406
+ error(`inject<{id}>(): {#candidates} providers; inject needs exactly one subsystem`)
407
+ end
408
+ local state = provider.state
409
+ local _result = state
410
+ if _result ~= nil then
411
+ _result = _result.phase
412
+ end
413
+ if _result == 5 then
414
+ error(`inject<{id}>(): provider {provider.id} is Faulted`)
415
+ end
416
+ local _object = state
417
+ if _object ~= nil then
418
+ _object = _object.object
419
+ end
420
+ local object = _object
421
+ if state == nil or object == nil or state.phase == 0 or state.phase == 1 then
422
+ error(`inject<{id}>(): {provider.id} is not awake yet; call inject from start or later, or take a constructor parameter`)
423
+ end
424
+ return object
425
+ end
426
+ --* @internal
427
+ function setFor(id)
428
+ local _id = id
429
+ local set = sets[_id]
430
+ if set == nil then
431
+ set = ImplementerSet.new(id)
432
+ local _id_1 = id
433
+ local _set = set
434
+ sets[_id_1] = _set
435
+ end
436
+ return set
437
+ end
438
+ return {
439
+ define = define,
440
+ plan = plan,
441
+ seal = seal,
442
+ records = records,
443
+ recordOf = recordOf,
444
+ resolveOne = resolveOne,
445
+ setFor = setFor,
446
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,117 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --* @internal
3
+ --* @internal
4
+ local robloxBindingPort
5
+ local function robloxPort()
6
+ local runService = game:GetService("RunService")
7
+ local events = {
8
+ [0] = runService.PreRender,
9
+ [1] = runService.PreSimulation,
10
+ [2] = runService.PostSimulation,
11
+ [3] = runService.RenderStepped,
12
+ [4] = runService.PreAnimation,
13
+ [5] = runService.Heartbeat,
14
+ }
15
+ local _object = table.clone(robloxBindingPort())
16
+ setmetatable(_object, nil)
17
+ _object.onFrame = function(event, listener)
18
+ local connection = events[event]:Connect(listener)
19
+ return function()
20
+ return connection:Disconnect()
21
+ end
22
+ end
23
+ _object.bindRenderStep = function(name, priority, listener)
24
+ runService:BindToRenderStep(name, priority, listener)
25
+ return function()
26
+ return runService:UnbindFromRenderStep(name)
27
+ end
28
+ end
29
+ _object.defer = function(callback)
30
+ task.defer(callback)
31
+ end
32
+ _object.cancel = function(thread)
33
+ return task.cancel(thread)
34
+ end
35
+ _object.spawn = function(callback)
36
+ task.spawn(callback)
37
+ end
38
+ _object.clock = function()
39
+ return os.clock()
40
+ end
41
+ _object.wait = function()
42
+ task.wait()
43
+ end
44
+ _object.bindToClose = function(callback)
45
+ return game:BindToClose(callback)
46
+ end
47
+ return _object
48
+ end
49
+ --* @internal
50
+ --* @internal
51
+ function robloxBindingPort()
52
+ local collection = game:GetService("CollectionService")
53
+ local excluded = { game:GetService("ServerStorage"), game:GetService("ReplicatedStorage"), game:GetService("ServerScriptService"), game:GetService("StarterGui"), game:GetService("StarterPack"), game:GetService("StarterPlayer") }
54
+ return {
55
+ hasTag = function(instance, tag)
56
+ return collection:HasTag(instance, tag)
57
+ end,
58
+ tagged = function(tag)
59
+ return collection:GetTagged(tag)
60
+ end,
61
+ onTagAdded = function(tag, listener)
62
+ local c = collection:GetInstanceAddedSignal(tag):Connect(listener)
63
+ return function()
64
+ return c:Disconnect()
65
+ end
66
+ end,
67
+ onTagRemoved = function(tag, listener)
68
+ local c = collection:GetInstanceRemovedSignal(tag):Connect(listener)
69
+ return function()
70
+ return c:Disconnect()
71
+ end
72
+ end,
73
+ inWorld = function(instance)
74
+ return instance:IsDescendantOf(game)
75
+ end,
76
+ isA = function(instance, name)
77
+ return instance:IsA(name)
78
+ end,
79
+ bindingScope = function(instance)
80
+ -- ▼ ReadonlyArray.some ▼
81
+ local _result = false
82
+ local _callback = function(container)
83
+ return instance == container or instance:IsDescendantOf(container)
84
+ end
85
+ for _k, _v in excluded do
86
+ if _callback(_v, _k - 1, excluded) then
87
+ _result = true
88
+ break
89
+ end
90
+ end
91
+ -- ▲ ReadonlyArray.some ▲
92
+ return not _result
93
+ end,
94
+ onAncestryChanged = function(instance, listener)
95
+ local c = instance.AncestryChanged:Connect(listener)
96
+ return function()
97
+ return c:Disconnect()
98
+ end
99
+ end,
100
+ getAttribute = function(instance, name)
101
+ return instance:GetAttribute(name)
102
+ end,
103
+ onAttributeChanged = function(instance, name, listener)
104
+ local c = instance:GetAttributeChangedSignal(name):Connect(listener)
105
+ return function()
106
+ return c:Disconnect()
107
+ end
108
+ end,
109
+ describe = function(instance)
110
+ return instance:GetFullName()
111
+ end,
112
+ }
113
+ end
114
+ return {
115
+ robloxPort = robloxPort,
116
+ robloxBindingPort = robloxBindingPort,
117
+ }
@@ -0,0 +1 @@
1
+ export {};