@quenty/binder 14.44.0 → 14.45.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/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [14.45.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@14.44.0...@quenty/binder@14.45.0) (2026-08-28)
7
+
8
+ **Note:** Version bump only for package @quenty/binder
9
+
6
10
  # [14.44.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@14.43.2...@quenty/binder@14.44.0) (2026-08-28)
7
11
 
8
12
  **Note:** Version bump only for package @quenty/binder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/binder",
3
- "version": "14.44.0",
3
+ "version": "14.45.0",
4
4
  "description": "Utility object to Bind a class to Roblox object, and associated helper methods",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -29,10 +29,11 @@
29
29
  ],
30
30
  "dependencies": {
31
31
  "@quenty/baseobject": "10.16.0",
32
- "@quenty/brio": "14.36.0",
32
+ "@quenty/brio": "14.37.0",
33
33
  "@quenty/canceltoken": "11.25.0",
34
- "@quenty/instanceutils": "13.36.0",
35
- "@quenty/linkutils": "13.37.0",
34
+ "@quenty/instanceutils": "13.37.0",
35
+ "@quenty/jestutils": "1.1.0",
36
+ "@quenty/linkutils": "13.38.0",
36
37
  "@quenty/loader": "10.11.1",
37
38
  "@quenty/maid": "3.12.0",
38
39
  "@quenty/nevermore-test-runner": "1.6.0",
@@ -41,11 +42,11 @@
41
42
  "@quenty/servicebag": "11.21.0",
42
43
  "@quenty/signal": "7.13.2",
43
44
  "@quenty/table": "3.9.2",
44
- "@quenty/valueobject": "13.37.0",
45
+ "@quenty/valueobject": "13.38.0",
45
46
  "@quentystudios/jest-lua": "3.10.0-quenty.2"
46
47
  },
47
48
  "publishConfig": {
48
49
  "access": "public"
49
50
  },
50
- "gitHead": "f75f93d5b2ac51cf7da3b7599788dcce31fd8a29"
51
+ "gitHead": "346201e192e467cb71160f43029863853be855b5"
51
52
  }
@@ -49,6 +49,6 @@ describe("Binder load abandonment", function()
49
49
  expect(binder:Get(inst)).toBeNil()
50
50
  expect(constructed).toEqual(1)
51
51
 
52
- controller.destroy()
52
+ controller:Destroy()
53
53
  end)
54
54
  end)
@@ -43,7 +43,7 @@ describe("Binder:ObserveBrio()", function()
43
43
  expect(brios[1]:GetValue()).toEqual(class)
44
44
 
45
45
  sub:Destroy()
46
- controller.destroy()
46
+ controller:Destroy()
47
47
  end)
48
48
 
49
49
  it("emits immediately when the instance is already bound", function()
@@ -67,7 +67,7 @@ describe("Binder:ObserveBrio()", function()
67
67
  expect(brios[1]:GetValue()).toEqual(class)
68
68
 
69
69
  sub:Destroy()
70
- controller.destroy()
70
+ controller:Destroy()
71
71
  end)
72
72
 
73
73
  it("kills the emitted brio when the instance unbinds", function()
@@ -93,7 +93,7 @@ describe("Binder:ObserveBrio()", function()
93
93
  expect(brios[1]:IsDead()).toEqual(true)
94
94
 
95
95
  sub:Destroy()
96
- controller.destroy()
96
+ controller:Destroy()
97
97
  end)
98
98
 
99
99
  it("emits a fresh live brio when the instance rebinds", function()
@@ -125,7 +125,7 @@ describe("Binder:ObserveBrio()", function()
125
125
  expect(brios[2]:GetValue()).toEqual(class)
126
126
 
127
127
  sub:Destroy()
128
- controller.destroy()
128
+ controller:Destroy()
129
129
  end)
130
130
  end)
131
131
 
@@ -153,7 +153,7 @@ describe("Binder:ObserveAllBrio()", function()
153
153
  expect(values[binder:Get(instB)]).toEqual(true)
154
154
 
155
155
  sub:Destroy()
156
- controller.destroy()
156
+ controller:Destroy()
157
157
  end)
158
158
 
159
159
  it("emits a brio when a new class is added", function()
@@ -178,7 +178,7 @@ describe("Binder:ObserveAllBrio()", function()
178
178
  expect(brios[1]:GetValue()).toEqual(binder:Get(inst))
179
179
 
180
180
  sub:Destroy()
181
- controller.destroy()
181
+ controller:Destroy()
182
182
  end)
183
183
 
184
184
  it("kills the brio when the class is removed", function()
@@ -204,6 +204,6 @@ describe("Binder:ObserveAllBrio()", function()
204
204
  expect(brios[1]:IsDead()).toEqual(true)
205
205
 
206
206
  sub:Destroy()
207
- controller.destroy()
207
+ controller:Destroy()
208
208
  end)
209
209
  end)
@@ -58,7 +58,7 @@ describe("Binder.new()", function()
58
58
  expect(class.a).toEqual("a")
59
59
  expect(class.b).toEqual("b")
60
60
 
61
- controller.destroy()
61
+ controller:Destroy()
62
62
  end)
63
63
  end)
64
64
 
@@ -109,7 +109,7 @@ describe("Binder constructor variants", function()
109
109
  expect(class.kind).toEqual("function")
110
110
  expect(class.instance).toEqual(inst)
111
111
 
112
- controller.destroy()
112
+ controller:Destroy()
113
113
  end)
114
114
 
115
115
  it("supports a class table with .new", function()
@@ -126,7 +126,7 @@ describe("Binder constructor variants", function()
126
126
  assert(ok, "Never bound")
127
127
  expect(class.instance).toEqual(inst)
128
128
 
129
- controller.destroy()
129
+ controller:Destroy()
130
130
  end)
131
131
 
132
132
  it("supports a provider table with :Create", function()
@@ -147,7 +147,7 @@ describe("Binder constructor variants", function()
147
147
  assert(ok, "Never bound")
148
148
  expect(class.kind).toEqual("provider")
149
149
 
150
- controller.destroy()
150
+ controller:Destroy()
151
151
  end)
152
152
  end)
153
153
 
@@ -192,7 +192,7 @@ describe("Binder binding via ServiceBag", function()
192
192
 
193
193
  expect(binder:Get(inst)).never.toBeNil()
194
194
 
195
- controller.destroy()
195
+ controller:Destroy()
196
196
  end)
197
197
 
198
198
  it("binds instances tagged after start", function()
@@ -207,7 +207,7 @@ describe("Binder binding via ServiceBag", function()
207
207
  local ok = binder:Promise(inst):Yield()
208
208
  expect(ok).toEqual(true)
209
209
 
210
- controller.destroy()
210
+ controller:Destroy()
211
211
  end)
212
212
  end)
213
213
 
@@ -220,7 +220,7 @@ describe("Binder:Get()", function()
220
220
 
221
221
  expect(binder:Get(controller.newInstance())).toBeNil()
222
222
 
223
- controller.destroy()
223
+ controller:Destroy()
224
224
  end)
225
225
 
226
226
  it("throws when passed a non-instance", function()
@@ -233,7 +233,7 @@ describe("Binder:Get()", function()
233
233
  binder:Get(5 :: any)
234
234
  end).toThrow()
235
235
 
236
- controller.destroy()
236
+ controller:Destroy()
237
237
  end)
238
238
  end)
239
239
 
@@ -251,7 +251,7 @@ describe("Binder tagging", function()
251
251
  binder:Untag(inst)
252
252
  expect(binder:HasTag(inst)).toEqual(false)
253
253
 
254
- controller.destroy()
254
+ controller:Destroy()
255
255
  end)
256
256
 
257
257
  it("Bind tags and Unbind untags on the server", function()
@@ -270,7 +270,7 @@ describe("Binder tagging", function()
270
270
  binder:Unbind(inst)
271
271
  expect(binder:HasTag(inst)).toEqual(false)
272
272
 
273
- controller.destroy()
273
+ controller:Destroy()
274
274
  end)
275
275
  end)
276
276
 
@@ -325,7 +325,7 @@ describe("Binder:GetAll() / GetAllSet()", function()
325
325
  expect(set[binder:Get(instA)]).toEqual(true)
326
326
  expect(set[binder:Get(instB)]).toEqual(true)
327
327
 
328
- controller.destroy()
328
+ controller:Destroy()
329
329
  end)
330
330
  end)
331
331
 
@@ -340,7 +340,7 @@ describe("Binder signals", function()
340
340
  expect(binder:GetClassRemovingSignal()).toEqual(binder:GetClassRemovingSignal())
341
341
  expect(binder:GetClassRemovedSignal()).toEqual(binder:GetClassRemovedSignal())
342
342
 
343
- controller.destroy()
343
+ controller:Destroy()
344
344
  end)
345
345
 
346
346
  it("fires the added signal with the class and instance", function()
@@ -362,7 +362,7 @@ describe("Binder signals", function()
362
362
  expect(firedInst).toEqual(inst)
363
363
  expect(firedClass).toEqual(binder:Get(inst))
364
364
 
365
- controller.destroy()
365
+ controller:Destroy()
366
366
  end)
367
367
 
368
368
  it("fires removing then removed on unbind", function()
@@ -389,7 +389,7 @@ describe("Binder signals", function()
389
389
  expect(order[1]).toEqual("removing")
390
390
  expect(order[2]).toEqual("removed")
391
391
 
392
- controller.destroy()
392
+ controller:Destroy()
393
393
  end)
394
394
 
395
395
  it("destroys the bound class when it is removed", function()
@@ -408,7 +408,7 @@ describe("Binder signals", function()
408
408
 
409
409
  expect(class.destroyed).toEqual(true)
410
410
 
411
- controller.destroy()
411
+ controller:Destroy()
412
412
  end)
413
413
  end)
414
414
 
@@ -440,7 +440,7 @@ describe("Binder:ObserveInstance()", function()
440
440
 
441
441
  cleanup()
442
442
 
443
- controller.destroy()
443
+ controller:Destroy()
444
444
  end)
445
445
 
446
446
  it("returns a cleanup that stops future callbacks", function()
@@ -462,7 +462,7 @@ describe("Binder:ObserveInstance()", function()
462
462
 
463
463
  expect(count).toEqual(0)
464
464
 
465
- controller.destroy()
465
+ controller:Destroy()
466
466
  end)
467
467
 
468
468
  it("throws for a non-instance or non-function", function()
@@ -478,7 +478,7 @@ describe("Binder:ObserveInstance()", function()
478
478
  binder:ObserveInstance(controller.newInstance(), 5 :: any)
479
479
  end).toThrow()
480
480
 
481
- controller.destroy()
481
+ controller:Destroy()
482
482
  end)
483
483
  end)
484
484
 
@@ -507,7 +507,7 @@ describe("Binder:Observe()", function()
507
507
  expect(emissions[2].value).toEqual(binder:Get(inst))
508
508
 
509
509
  sub:Destroy()
510
- controller.destroy()
510
+ controller:Destroy()
511
511
  end)
512
512
  end)
513
513
 
@@ -524,7 +524,7 @@ describe("Binder:Promise()", function()
524
524
  local promise = binder:Promise(inst)
525
525
  expect(promise:IsFulfilled()).toEqual(true)
526
526
 
527
- controller.destroy()
527
+ controller:Destroy()
528
528
  end)
529
529
 
530
530
  it("throws when passed a non-instance", function()
@@ -537,7 +537,7 @@ describe("Binder:Promise()", function()
537
537
  binder:Promise(5 :: any)
538
538
  end).toThrow()
539
539
 
540
- controller.destroy()
540
+ controller:Destroy()
541
541
  end)
542
542
  end)
543
543
 
@@ -561,7 +561,7 @@ describe("Binder:_add() dedupe", function()
561
561
 
562
562
  expect(constructed).toEqual(1)
563
563
 
564
- controller.destroy()
564
+ controller:Destroy()
565
565
  end)
566
566
  end)
567
567
 
@@ -581,6 +581,6 @@ describe("Binder teardown", function()
581
581
 
582
582
  expect(class.destroyed).toEqual(true)
583
583
 
584
- controller.destroy()
584
+ controller:Destroy()
585
585
  end)
586
586
  end)
@@ -8,6 +8,8 @@ local require = require(script.Parent.loader).load(script)
8
8
  local Binder = require("Binder")
9
9
  local BinderGroup = require("BinderGroup")
10
10
  local Jest = require("Jest")
11
+ local JestUtils = require("JestUtils")
12
+ local Maid = require("Maid")
11
13
 
12
14
  local describe = Jest.Globals.describe
13
15
  local expect = Jest.Globals.expect
@@ -16,6 +18,8 @@ local it = Jest.Globals.it
16
18
  local tagCounter = 0
17
19
 
18
20
  local function setup()
21
+ local maid = Maid.new()
22
+
19
23
  local binders: { any } = {}
20
24
 
21
25
  local function newBinder(): Binder.Binder<any>
@@ -27,16 +31,24 @@ local function setup()
27
31
  return binder
28
32
  end
29
33
 
30
- return {
34
+ maid:GiveTask(function()
35
+ for _, binder in binders do
36
+ pcall(function()
37
+ binder:Destroy()
38
+ end)
39
+ end
40
+ end)
41
+
42
+ local controller = {
31
43
  newBinder = newBinder,
32
- destroy = function()
33
- for _, binder in binders do
34
- pcall(function()
35
- binder:Destroy()
36
- end)
37
- end
44
+ Destroy = function(_self)
45
+ maid:DoCleaning()
38
46
  end,
39
47
  }
48
+
49
+ maid:GiveTask(JestUtils.afterThis(controller))
50
+
51
+ return controller
40
52
  end
41
53
 
42
54
  describe("BinderGroup.new()", function()
@@ -49,7 +61,7 @@ describe("BinderGroup.new()", function()
49
61
 
50
62
  expect(#group:GetBinders()).toEqual(2)
51
63
 
52
- controller.destroy()
64
+ controller:Destroy()
53
65
  end)
54
66
 
55
67
  it("constructs empty", function()
@@ -68,7 +80,7 @@ describe("BinderGroup:Add()", function()
68
80
 
69
81
  expect(group:GetBinders()[1]).toEqual(binder)
70
82
 
71
- controller.destroy()
83
+ controller:Destroy()
72
84
  end)
73
85
 
74
86
  it("fires BinderAdded with the added binder", function()
@@ -85,7 +97,7 @@ describe("BinderGroup:Add()", function()
85
97
 
86
98
  expect(fired).toEqual(binder)
87
99
 
88
- controller.destroy()
100
+ controller:Destroy()
89
101
  end)
90
102
 
91
103
  it("throws when the value is not a binder", function()
@@ -111,7 +123,7 @@ describe("BinderGroup constructor validation", function()
111
123
 
112
124
  expect(validated[1]).toEqual(binder:GetConstructor())
113
125
 
114
- controller.destroy()
126
+ controller:Destroy()
115
127
  end)
116
128
 
117
129
  it("throws when the constructor fails validation", function()
@@ -126,7 +138,7 @@ describe("BinderGroup constructor validation", function()
126
138
  group:Add(binder)
127
139
  end).toThrow()
128
140
 
129
- controller.destroy()
141
+ controller:Destroy()
130
142
  end)
131
143
  end)
132
144
 
@@ -139,7 +151,7 @@ describe("BinderGroup:AddList()", function()
139
151
 
140
152
  expect(#group:GetBinders()).toEqual(2)
141
153
 
142
- controller.destroy()
154
+ controller:Destroy()
143
155
  end)
144
156
 
145
157
  it("throws on a non-table argument", function()
@@ -7,7 +7,7 @@
7
7
 
8
8
  Tags are global and the test place is shared across a batch run, so every binder gets a distinct
9
9
  tag from a single module-level counter -- shared across every spec file that requires this module,
10
- so tags never collide between files -- and each controller cleans up after itself via `destroy()`.
10
+ so tags never collide between files -- and each controller cleans up after itself via `Destroy()`.
11
11
 
12
12
  @class BinderTestUtils
13
13
  ]=]
@@ -16,6 +16,8 @@ local require = require(script.Parent.loader).load(script)
16
16
 
17
17
  local Binder = require("Binder")
18
18
  local BinderProvider = require("BinderProvider")
19
+ local JestUtils = require("JestUtils")
20
+ local Maid = require("Maid")
19
21
  local ServiceBag = require("ServiceBag")
20
22
 
21
23
  local BinderTestUtils = {}
@@ -74,11 +76,11 @@ end
74
76
  --[=[
75
77
  Builds the controller the Binder specs share. Register binders with `addBinder`, boot them all at
76
78
  once through a ServiceBag with `boot`, create adornees with `newInstance`, and tear everything down
77
- with `destroy` (or just the service bag with `destroyServiceBag`).
79
+ with `Destroy` (or just the service bag with `destroyServiceBag`).
78
80
 
79
81
  Fields: `container`.
80
82
  Builders: `addBinder(constructor, ...)` -> Binder, `newInstance(parent?, className?)` -> Instance.
81
- Lifecycle: `boot()`, `destroyServiceBag()`, `destroy()`.
83
+ Lifecycle: `boot()`, `destroyServiceBag()`, `Destroy()`.
82
84
  Helpers: `uniqueTag()` -> string.
83
85
 
84
86
  @return { ... }
@@ -87,6 +89,8 @@ function BinderTestUtils.setup()
87
89
  specCounter += 1
88
90
  local suffix = specCounter
89
91
 
92
+ local maid = Maid.new()
93
+
90
94
  local serviceBag = ServiceBag.new()
91
95
  local serviceBagDestroyed = false
92
96
 
@@ -141,23 +145,31 @@ function BinderTestUtils.setup()
141
145
  end
142
146
  end
143
147
 
144
- return {
148
+ maid:GiveTask(function()
149
+ destroyServiceBag()
150
+ for _, inst in instances do
151
+ pcall(function()
152
+ inst:Destroy()
153
+ end)
154
+ end
155
+ container:Destroy()
156
+ end)
157
+
158
+ local controller = {
145
159
  container = container,
146
160
  uniqueTag = uniqueTag,
147
161
  addBinder = addBinder,
148
162
  boot = boot,
149
163
  newInstance = newInstance,
150
164
  destroyServiceBag = destroyServiceBag,
151
- destroy = function()
152
- destroyServiceBag()
153
- for _, inst in instances do
154
- pcall(function()
155
- inst:Destroy()
156
- end)
157
- end
158
- container:Destroy()
165
+ Destroy = function(_self)
166
+ maid:DoCleaning()
159
167
  end,
160
168
  }
169
+
170
+ maid:GiveTask(JestUtils.afterThis(controller))
171
+
172
+ return controller
161
173
  end
162
174
 
163
175
  return BinderTestUtils
@@ -9,6 +9,8 @@ local Binder = require("Binder")
9
9
  local BinderProvider = require("BinderProvider")
10
10
  local BinderUtils = require("BinderUtils")
11
11
  local Jest = require("Jest")
12
+ local JestUtils = require("JestUtils")
13
+ local Maid = require("Maid")
12
14
  local ServiceBag = require("ServiceBag")
13
15
 
14
16
  local describe = Jest.Globals.describe
@@ -29,6 +31,8 @@ local function makeClass()
29
31
  end
30
32
 
31
33
  local function setup()
34
+ local maid = Maid.new()
35
+
32
36
  specCounter += 1
33
37
  local suffix = specCounter
34
38
 
@@ -37,7 +41,7 @@ local function setup()
37
41
  container.Name = "BinderUtilsSpecContainer"
38
42
  container.Parent = workspace
39
43
 
40
- local instances = {}
44
+ local instances: { Instance } = {}
41
45
  local pendingBinders: { any } = {}
42
46
  local tagCounter = 0
43
47
  local booted = false
@@ -72,21 +76,29 @@ local function setup()
72
76
  serviceBag:Start()
73
77
  end
74
78
 
75
- return {
79
+ maid:GiveTask(function()
80
+ serviceBag:Destroy()
81
+ for _, inst in instances do
82
+ pcall(function()
83
+ inst:Destroy()
84
+ end)
85
+ end
86
+ container:Destroy()
87
+ end)
88
+
89
+ local controller = {
76
90
  container = container,
77
91
  newBinder = newBinder,
78
92
  newInstance = newInstance,
79
93
  boot = boot,
80
- destroy = function()
81
- serviceBag:Destroy()
82
- for _, inst in instances do
83
- pcall(function()
84
- inst:Destroy()
85
- end)
86
- end
87
- container:Destroy()
94
+ Destroy = function(_self)
95
+ maid:DoCleaning()
88
96
  end,
89
97
  }
98
+
99
+ maid:GiveTask(JestUtils.afterThis(controller))
100
+
101
+ return controller
90
102
  end
91
103
 
92
104
  describe("BinderUtils.findFirstAncestor()", function()
@@ -104,7 +116,7 @@ describe("BinderUtils.findFirstAncestor()", function()
104
116
 
105
117
  expect(BinderUtils.findFirstAncestor(binder, child)).toEqual(binder:Get(grandparent))
106
118
 
107
- controller.destroy()
119
+ controller:Destroy()
108
120
  end)
109
121
 
110
122
  it("returns nil when no ancestor is bound", function()
@@ -117,7 +129,7 @@ describe("BinderUtils.findFirstAncestor()", function()
117
129
 
118
130
  expect(BinderUtils.findFirstAncestor(binder, child)).toBeNil()
119
131
 
120
- controller.destroy()
132
+ controller:Destroy()
121
133
  end)
122
134
 
123
135
  it("throws for a non-instance child", function()
@@ -129,7 +141,7 @@ describe("BinderUtils.findFirstAncestor()", function()
129
141
  BinderUtils.findFirstAncestor(binder, 5 :: any)
130
142
  end).toThrow()
131
143
 
132
- controller.destroy()
144
+ controller:Destroy()
133
145
  end)
134
146
  end)
135
147
 
@@ -148,7 +160,7 @@ describe("BinderUtils.findFirstChild()", function()
148
160
  expect(BinderUtils.findFirstChild(binder, parent)).toEqual(binder:Get(boundChild))
149
161
  expect(binder:Get(unboundChild)).toBeNil()
150
162
 
151
- controller.destroy()
163
+ controller:Destroy()
152
164
  end)
153
165
 
154
166
  it("returns nil when no child is bound", function()
@@ -161,7 +173,7 @@ describe("BinderUtils.findFirstChild()", function()
161
173
 
162
174
  expect(BinderUtils.findFirstChild(binder, parent)).toBeNil()
163
175
 
164
- controller.destroy()
176
+ controller:Destroy()
165
177
  end)
166
178
  end)
167
179
 
@@ -181,7 +193,7 @@ describe("BinderUtils.getChildren()", function()
181
193
 
182
194
  expect(#BinderUtils.getChildren(binder, parent)).toEqual(2)
183
195
 
184
- controller.destroy()
196
+ controller:Destroy()
185
197
  end)
186
198
 
187
199
  it("does not include bound descendants deeper than one level", function()
@@ -197,7 +209,7 @@ describe("BinderUtils.getChildren()", function()
197
209
 
198
210
  expect(#BinderUtils.getChildren(binder, parent)).toEqual(0)
199
211
 
200
- controller.destroy()
212
+ controller:Destroy()
201
213
  end)
202
214
  end)
203
215
 
@@ -216,7 +228,7 @@ describe("BinderUtils.getDescendants()", function()
216
228
 
217
229
  expect(#BinderUtils.getDescendants(binder, parent)).toEqual(2)
218
230
 
219
- controller.destroy()
231
+ controller:Destroy()
220
232
  end)
221
233
  end)
222
234
 
@@ -232,7 +244,7 @@ describe("BinderUtils.mapBinderListToTable()", function()
232
244
  expect(map[binderA:GetTag()]).toEqual(binderA)
233
245
  expect(map[binderB:GetTag()]).toEqual(binderB)
234
246
 
235
- controller.destroy()
247
+ controller:Destroy()
236
248
  end)
237
249
  end)
238
250
 
@@ -253,7 +265,7 @@ describe("BinderUtils.getMappedFromList()", function()
253
265
 
254
266
  expect(#objects).toEqual(2)
255
267
 
256
- controller.destroy()
268
+ controller:Destroy()
257
269
  end)
258
270
  end)
259
271
 
@@ -273,7 +285,7 @@ describe("BinderUtils.getChildrenOfBinders()", function()
273
285
 
274
286
  expect(#BinderUtils.getChildrenOfBinders({ binderA, binderB }, parent)).toEqual(2)
275
287
 
276
- controller.destroy()
288
+ controller:Destroy()
277
289
  end)
278
290
  end)
279
291
 
@@ -295,7 +307,7 @@ describe("BinderUtils.getLinkedChildren()", function()
295
307
  expect(#objects).toEqual(1)
296
308
  expect(objects[1]).toEqual(binder:Get(target))
297
309
 
298
- controller.destroy()
310
+ controller:Destroy()
299
311
  end)
300
312
 
301
313
  it("ignores links whose name does not match", function()
@@ -313,7 +325,7 @@ describe("BinderUtils.getLinkedChildren()", function()
313
325
 
314
326
  expect(#BinderUtils.getLinkedChildren(binder, "Link", parent)).toEqual(0)
315
327
 
316
- controller.destroy()
328
+ controller:Destroy()
317
329
  end)
318
330
 
319
331
  it("deduplicates when two links point to the same bound target", function()
@@ -333,6 +345,6 @@ describe("BinderUtils.getLinkedChildren()", function()
333
345
 
334
346
  expect(#BinderUtils.getLinkedChildren(binder, "Link", parent)).toEqual(1)
335
347
 
336
- controller.destroy()
348
+ controller:Destroy()
337
349
  end)
338
350
  end)
@@ -9,6 +9,8 @@ local Binder = require("Binder")
9
9
  local BinderProvider = require("BinderProvider")
10
10
  local BoundChildCollection = require("BoundChildCollection")
11
11
  local Jest = require("Jest")
12
+ local JestUtils = require("JestUtils")
13
+ local Maid = require("Maid")
12
14
  local ServiceBag = require("ServiceBag")
13
15
 
14
16
  local describe = Jest.Globals.describe
@@ -29,6 +31,8 @@ local function makeClass()
29
31
  end
30
32
 
31
33
  local function setup()
34
+ local maid = Maid.new()
35
+
32
36
  specCounter += 1
33
37
  local suffix = specCounter
34
38
 
@@ -37,8 +41,8 @@ local function setup()
37
41
  container.Name = "BoundChildCollectionSpecContainer"
38
42
  container.Parent = workspace
39
43
 
40
- local instances = {}
41
- local cleanups = {}
44
+ local instances: { Instance } = {}
45
+ local cleanups: { any } = {}
42
46
  local booted = false
43
47
 
44
48
  local binder = Binder.new(string.format("BoundChildCollectionSpecTag_%d", suffix), makeClass() :: any)
@@ -67,27 +71,35 @@ local function setup()
67
71
  serviceBag:Start()
68
72
  end
69
73
 
70
- return {
74
+ maid:GiveTask(function()
75
+ for _, item in cleanups do
76
+ pcall(function()
77
+ item:Destroy()
78
+ end)
79
+ end
80
+ serviceBag:Destroy()
81
+ for _, inst in instances do
82
+ pcall(function()
83
+ inst:Destroy()
84
+ end)
85
+ end
86
+ container:Destroy()
87
+ end)
88
+
89
+ local controller = {
71
90
  container = container,
72
91
  binder = binder,
73
92
  newInstance = newInstance,
74
93
  track = track,
75
94
  boot = boot,
76
- destroy = function()
77
- for _, item in cleanups do
78
- pcall(function()
79
- item:Destroy()
80
- end)
81
- end
82
- serviceBag:Destroy()
83
- for _, inst in instances do
84
- pcall(function()
85
- inst:Destroy()
86
- end)
87
- end
88
- container:Destroy()
95
+ Destroy = function(_self)
96
+ maid:DoCleaning()
89
97
  end,
90
98
  }
99
+
100
+ maid:GiveTask(JestUtils.afterThis(controller))
101
+
102
+ return controller
91
103
  end
92
104
 
93
105
  describe("BoundChildCollection construction", function()
@@ -114,7 +126,7 @@ describe("BoundChildCollection construction", function()
114
126
  expect(#collection:GetClasses()).toEqual(2)
115
127
  expect(collection:HasClass(controller.binder:Get(childA))).toEqual(true)
116
128
 
117
- controller.destroy()
129
+ controller:Destroy()
118
130
  end)
119
131
  end)
120
132
 
@@ -146,7 +158,7 @@ describe("BoundChildCollection dynamic updates", function()
146
158
  expect(addedClass).toEqual(class)
147
159
  expect(collection:GetSize()).toEqual(1)
148
160
 
149
- controller.destroy()
161
+ controller:Destroy()
150
162
  end)
151
163
 
152
164
  it("fires ClassRemoved when a tracked child is reparented out", function()
@@ -175,7 +187,7 @@ describe("BoundChildCollection dynamic updates", function()
175
187
  expect(removedClass).toEqual(class)
176
188
  expect(collection:GetSize()).toEqual(0)
177
189
 
178
- controller.destroy()
190
+ controller:Destroy()
179
191
  end)
180
192
 
181
193
  it("fires ClassRemoved when a tracked child is unbound", function()
@@ -198,6 +210,6 @@ describe("BoundChildCollection dynamic updates", function()
198
210
 
199
211
  expect(collection:GetSize()).toEqual(0)
200
212
 
201
- controller.destroy()
213
+ controller:Destroy()
202
214
  end)
203
215
  end)
@@ -8,6 +8,8 @@ local require = require(script.Parent.loader).load(script)
8
8
  local Binder = require("Binder")
9
9
  local BinderProvider = require("BinderProvider")
10
10
  local Jest = require("Jest")
11
+ local JestUtils = require("JestUtils")
12
+ local Maid = require("Maid")
11
13
  local ServiceBag = require("ServiceBag")
12
14
  local promiseBoundClass = require("promiseBoundClass")
13
15
 
@@ -29,6 +31,8 @@ local function makeClass()
29
31
  end
30
32
 
31
33
  local function setup()
34
+ local maid = Maid.new()
35
+
32
36
  specCounter += 1
33
37
  local suffix = specCounter
34
38
 
@@ -37,7 +41,7 @@ local function setup()
37
41
  container.Name = "PromiseBoundClassSpecContainer"
38
42
  container.Parent = workspace
39
43
 
40
- local instances = {}
44
+ local instances: { Instance } = {}
41
45
  local booted = false
42
46
 
43
47
  local binder = Binder.new(string.format("PromiseBoundClassSpecTag_%d", suffix), makeClass() :: any)
@@ -61,20 +65,28 @@ local function setup()
61
65
  serviceBag:Start()
62
66
  end
63
67
 
64
- return {
68
+ maid:GiveTask(function()
69
+ serviceBag:Destroy()
70
+ for _, inst in instances do
71
+ pcall(function()
72
+ inst:Destroy()
73
+ end)
74
+ end
75
+ container:Destroy()
76
+ end)
77
+
78
+ local controller = {
65
79
  binder = binder,
66
80
  newInstance = newInstance,
67
81
  boot = boot,
68
- destroy = function()
69
- serviceBag:Destroy()
70
- for _, inst in instances do
71
- pcall(function()
72
- inst:Destroy()
73
- end)
74
- end
75
- container:Destroy()
82
+ Destroy = function(_self)
83
+ maid:DoCleaning()
76
84
  end,
77
85
  }
86
+
87
+ maid:GiveTask(JestUtils.afterThis(controller))
88
+
89
+ return controller
78
90
  end
79
91
 
80
92
  describe("promiseBoundClass()", function()
@@ -89,7 +101,7 @@ describe("promiseBoundClass()", function()
89
101
  assert(ok, "Never bound")
90
102
  expect(class).toEqual(controller.binder:Get(inst))
91
103
 
92
- controller.destroy()
104
+ controller:Destroy()
93
105
  end)
94
106
 
95
107
  it("resolves once an instance is bound after start", function()
@@ -102,7 +114,7 @@ describe("promiseBoundClass()", function()
102
114
  local ok = promiseBoundClass(controller.binder, inst):Yield()
103
115
  expect(ok).toEqual(true)
104
116
 
105
- controller.destroy()
117
+ controller:Destroy()
106
118
  end)
107
119
 
108
120
  it("throws when the binder is not a binder", function()
@@ -113,7 +125,7 @@ describe("promiseBoundClass()", function()
113
125
  promiseBoundClass({} :: any, controller.newInstance())
114
126
  end).toThrow()
115
127
 
116
- controller.destroy()
128
+ controller:Destroy()
117
129
  end)
118
130
 
119
131
  it("throws when the instance is not an Instance", function()
@@ -124,6 +136,6 @@ describe("promiseBoundClass()", function()
124
136
  promiseBoundClass(controller.binder, 5 :: any)
125
137
  end).toThrow()
126
138
 
127
- controller.destroy()
139
+ controller:Destroy()
128
140
  end)
129
141
  end)
@@ -9,6 +9,8 @@ local Binder = require("Binder")
9
9
  local BinderProvider = require("BinderProvider")
10
10
  local BoundAncestorTracker = require("BoundAncestorTracker")
11
11
  local Jest = require("Jest")
12
+ local JestUtils = require("JestUtils")
13
+ local Maid = require("Maid")
12
14
  local ServiceBag = require("ServiceBag")
13
15
 
14
16
  local describe = Jest.Globals.describe
@@ -29,6 +31,8 @@ local function makeClass()
29
31
  end
30
32
 
31
33
  local function setup()
34
+ local maid = Maid.new()
35
+
32
36
  specCounter += 1
33
37
  local suffix = specCounter
34
38
 
@@ -37,8 +41,8 @@ local function setup()
37
41
  container.Name = "BoundAncestorTrackerSpecContainer"
38
42
  container.Parent = workspace
39
43
 
40
- local instances = {}
41
- local cleanups = {}
44
+ local instances: { Instance } = {}
45
+ local cleanups: { any } = {}
42
46
  local booted = false
43
47
 
44
48
  local binder = Binder.new(string.format("BoundAncestorTrackerSpecTag_%d", suffix), makeClass() :: any)
@@ -74,28 +78,36 @@ local function setup()
74
78
  return tracker.Class.Value
75
79
  end
76
80
 
77
- return {
81
+ maid:GiveTask(function()
82
+ for _, item in cleanups do
83
+ pcall(function()
84
+ item:Destroy()
85
+ end)
86
+ end
87
+ serviceBag:Destroy()
88
+ for _, inst in instances do
89
+ pcall(function()
90
+ inst:Destroy()
91
+ end)
92
+ end
93
+ container:Destroy()
94
+ end)
95
+
96
+ local controller = {
78
97
  container = container,
79
98
  binder = binder,
80
99
  newInstance = newInstance,
81
100
  track = track,
82
101
  boot = boot,
83
102
  awaitChange = awaitChange,
84
- destroy = function()
85
- for _, item in cleanups do
86
- pcall(function()
87
- item:Destroy()
88
- end)
89
- end
90
- serviceBag:Destroy()
91
- for _, inst in instances do
92
- pcall(function()
93
- inst:Destroy()
94
- end)
95
- end
96
- container:Destroy()
103
+ Destroy = function(_self)
104
+ maid:DoCleaning()
97
105
  end,
98
106
  }
107
+
108
+ maid:GiveTask(JestUtils.afterThis(controller))
109
+
110
+ return controller
99
111
  end
100
112
 
101
113
  describe("BoundAncestorTracker tracking", function()
@@ -111,7 +123,7 @@ describe("BoundAncestorTracker tracking", function()
111
123
  local tracker = controller.track(BoundAncestorTracker.new(controller.binder, child))
112
124
  expect(tracker.Class.Value).toEqual(controller.binder:Get(grandparent))
113
125
 
114
- controller.destroy()
126
+ controller:Destroy()
115
127
  end)
116
128
 
117
129
  it("has no value when no ancestor is bound", function()
@@ -124,7 +136,7 @@ describe("BoundAncestorTracker tracking", function()
124
136
  local tracker = controller.track(BoundAncestorTracker.new(controller.binder, child))
125
137
  expect(tracker.Class.Value).toBeNil()
126
138
 
127
- controller.destroy()
139
+ controller:Destroy()
128
140
  end)
129
141
 
130
142
  it("updates when an ancestor becomes bound", function()
@@ -143,7 +155,7 @@ describe("BoundAncestorTracker tracking", function()
143
155
  local value = controller.awaitChange(tracker, nil)
144
156
  expect(value).toEqual(controller.binder:Get(ancestor))
145
157
 
146
- controller.destroy()
158
+ controller:Destroy()
147
159
  end)
148
160
 
149
161
  it("clears the value when the child leaves the bound ancestry", function()
@@ -162,6 +174,6 @@ describe("BoundAncestorTracker tracking", function()
162
174
  child.Parent = controller.container
163
175
  expect(controller.awaitChange(tracker, class)).toBeNil()
164
176
 
165
- controller.destroy()
177
+ controller:Destroy()
166
178
  end)
167
179
  end)
@@ -9,6 +9,8 @@ local Binder = require("Binder")
9
9
  local BinderProvider = require("BinderProvider")
10
10
  local BoundParentTracker = require("BoundParentTracker")
11
11
  local Jest = require("Jest")
12
+ local JestUtils = require("JestUtils")
13
+ local Maid = require("Maid")
12
14
  local ServiceBag = require("ServiceBag")
13
15
 
14
16
  local describe = Jest.Globals.describe
@@ -29,6 +31,8 @@ local function makeClass()
29
31
  end
30
32
 
31
33
  local function setup()
34
+ local maid = Maid.new()
35
+
32
36
  specCounter += 1
33
37
  local suffix = specCounter
34
38
 
@@ -37,8 +41,8 @@ local function setup()
37
41
  container.Name = "BoundParentTrackerSpecContainer"
38
42
  container.Parent = workspace
39
43
 
40
- local instances = {}
41
- local cleanups = {}
44
+ local instances: { Instance } = {}
45
+ local cleanups: { any } = {}
42
46
  local booted = false
43
47
 
44
48
  local binder = Binder.new(string.format("BoundParentTrackerSpecTag_%d", suffix), makeClass() :: any)
@@ -74,28 +78,36 @@ local function setup()
74
78
  return tracker.Class.Value
75
79
  end
76
80
 
77
- return {
81
+ maid:GiveTask(function()
82
+ for _, item in cleanups do
83
+ pcall(function()
84
+ item:Destroy()
85
+ end)
86
+ end
87
+ serviceBag:Destroy()
88
+ for _, inst in instances do
89
+ pcall(function()
90
+ inst:Destroy()
91
+ end)
92
+ end
93
+ container:Destroy()
94
+ end)
95
+
96
+ local controller = {
78
97
  container = container,
79
98
  binder = binder,
80
99
  newInstance = newInstance,
81
100
  track = track,
82
101
  boot = boot,
83
102
  awaitChange = awaitChange,
84
- destroy = function()
85
- for _, item in cleanups do
86
- pcall(function()
87
- item:Destroy()
88
- end)
89
- end
90
- serviceBag:Destroy()
91
- for _, inst in instances do
92
- pcall(function()
93
- inst:Destroy()
94
- end)
95
- end
96
- container:Destroy()
103
+ Destroy = function(_self)
104
+ maid:DoCleaning()
97
105
  end,
98
106
  }
107
+
108
+ maid:GiveTask(JestUtils.afterThis(controller))
109
+
110
+ return controller
99
111
  end
100
112
 
101
113
  describe("BoundParentTracker.new()", function()
@@ -118,7 +130,7 @@ describe("BoundParentTracker tracking", function()
118
130
  local tracker = controller.track(BoundParentTracker.new(controller.binder, child))
119
131
  expect(tracker.Class.Value).toEqual(controller.binder:Get(parent))
120
132
 
121
- controller.destroy()
133
+ controller:Destroy()
122
134
  end)
123
135
 
124
136
  it("clears the value when the child is reparented off the bound parent", function()
@@ -136,7 +148,7 @@ describe("BoundParentTracker tracking", function()
136
148
  child.Parent = controller.container
137
149
  expect(controller.awaitChange(tracker, class)).toBeNil()
138
150
 
139
- controller.destroy()
151
+ controller:Destroy()
140
152
  end)
141
153
 
142
154
  it("clears the value when the parent's class is unbound", function()
@@ -154,6 +166,6 @@ describe("BoundParentTracker tracking", function()
154
166
  controller.binder:Untag(parent)
155
167
  expect(controller.awaitChange(tracker, class)).toBeNil()
156
168
 
157
- controller.destroy()
169
+ controller:Destroy()
158
170
  end)
159
171
  end)