@quenty/observablecollection 12.47.1 → 12.48.1
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,16 @@
|
|
|
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
|
+
## [12.48.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/observablecollection@12.48.0...@quenty/observablecollection@12.48.1) (2026-08-24)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- ObservableSortedList handles removal immediately. ([9f115e8](https://github.com/Quenty/NevermoreEngine/commit/9f115e8b32c5450f63904a1a39845e98f423712e))
|
|
11
|
+
|
|
12
|
+
# [12.48.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/observablecollection@12.47.1...@quenty/observablecollection@12.48.0) (2026-08-24)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @quenty/observablecollection
|
|
15
|
+
|
|
6
16
|
## [12.47.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/observablecollection@12.47.0...@quenty/observablecollection@12.47.1) (2026-08-14)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @quenty/observablecollection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/observablecollection",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.48.1",
|
|
4
4
|
"description": "A set of observable collections, such as sets, maps, sorted lists, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"@quentystudios/jest-lua": "3.10.0-quenty.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@quenty/blend": "12.
|
|
51
|
+
"@quenty/blend": "12.46.0"
|
|
52
52
|
},
|
|
53
53
|
"publishConfig": {
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "1a2c0cc735d06b4adcd324f60302b950e12d68b0"
|
|
57
57
|
}
|
|
@@ -50,6 +50,7 @@ export type ObservableSortedList<T> = typeof(setmetatable(
|
|
|
50
50
|
|
|
51
51
|
_unifiedTracker: UnifiedChangedSpanTracker.UnifiedChangedSpanTracker,
|
|
52
52
|
|
|
53
|
+
_nodeRemovedImmediate: Signal.Signal<SortedNode.SortedNode<T>>,
|
|
53
54
|
_indexObservers: any,
|
|
54
55
|
_nodeIndexObservables: any,
|
|
55
56
|
_mainObservables: any,
|
|
@@ -116,6 +117,10 @@ function ObservableSortedList.new<T>(isReversed: boolean?, compare: CompareFunct
|
|
|
116
117
|
]=]
|
|
117
118
|
self.OrderChanged = self._maid:Add(Signal.new())
|
|
118
119
|
|
|
120
|
+
-- Internal: fires the moment a node leaves the tree, ahead of the batched ItemRemoved, for
|
|
121
|
+
-- observers holding the node itself.
|
|
122
|
+
self._nodeRemovedImmediate = self._maid:Add(Signal.new()) :: any
|
|
123
|
+
|
|
119
124
|
--[=[
|
|
120
125
|
Fires when the count changes
|
|
121
126
|
|
|
@@ -286,6 +291,13 @@ function ObservableSortedList.ObserveItemsBrio<T>(
|
|
|
286
291
|
-- to so many events
|
|
287
292
|
|
|
288
293
|
local function handleItem(data: T, _index, node)
|
|
294
|
+
-- Nodes added before this subscription are announced from the tree below, and their
|
|
295
|
+
-- ItemAdded still fires on the next flush. Announcing twice would replace the brio the
|
|
296
|
+
-- subscriber is already holding.
|
|
297
|
+
if maid[node] then
|
|
298
|
+
return
|
|
299
|
+
end
|
|
300
|
+
|
|
289
301
|
local brio = Brio.new(data, node)
|
|
290
302
|
maid[node] = brio
|
|
291
303
|
sub:Fire(brio)
|
|
@@ -297,7 +309,7 @@ function ObservableSortedList.ObserveItemsBrio<T>(
|
|
|
297
309
|
end
|
|
298
310
|
|
|
299
311
|
maid:GiveTask(self.ItemAdded:Connect(handleItem))
|
|
300
|
-
maid:GiveTask(self.
|
|
312
|
+
maid:GiveTask(self._nodeRemovedImmediate:Connect(function(node)
|
|
301
313
|
maid[node] = nil
|
|
302
314
|
end))
|
|
303
315
|
|
|
@@ -494,6 +506,11 @@ function ObservableSortedList._assignSortValue<T>(
|
|
|
494
506
|
self:_removeNode(node)
|
|
495
507
|
node.value = nil
|
|
496
508
|
self:_queueFireEvents()
|
|
509
|
+
|
|
510
|
+
-- Holders of the node itself have to let go now, not on the next flush. A node added and
|
|
511
|
+
-- removed before that flush cancels both batched events, so ItemRemoved alone would
|
|
512
|
+
-- leave them holding a node that is no longer in the list.
|
|
513
|
+
self._nodeRemovedImmediate:Fire(node)
|
|
497
514
|
else
|
|
498
515
|
node.value = nil
|
|
499
516
|
end
|
|
@@ -1013,6 +1013,111 @@ describe("ObservableSortedList", function()
|
|
|
1013
1013
|
maid:Destroy()
|
|
1014
1014
|
end)
|
|
1015
1015
|
|
|
1016
|
+
it("should kill the brio of an item added and removed in the same frame", function()
|
|
1017
|
+
local maid = Maid.new()
|
|
1018
|
+
local list = maid:Add(ObservableSortedList.new())
|
|
1019
|
+
|
|
1020
|
+
local remove = list:Add("a", 1)
|
|
1021
|
+
|
|
1022
|
+
local brios: { any } = {}
|
|
1023
|
+
maid:GiveTask(list:ObserveItemsBrio():Subscribe(function(brio)
|
|
1024
|
+
table.insert(brios, brio)
|
|
1025
|
+
end))
|
|
1026
|
+
|
|
1027
|
+
expect(#brios).toEqual(1)
|
|
1028
|
+
expect(brios[1]:IsDead()).toEqual(false)
|
|
1029
|
+
|
|
1030
|
+
remove()
|
|
1031
|
+
|
|
1032
|
+
expect(brios[1]:IsDead()).toEqual(true)
|
|
1033
|
+
expect(list:GetList()).toEqual({})
|
|
1034
|
+
|
|
1035
|
+
list:_testForceFireEvents()
|
|
1036
|
+
|
|
1037
|
+
expect(brios[1]:IsDead()).toEqual(true)
|
|
1038
|
+
|
|
1039
|
+
maid:Destroy()
|
|
1040
|
+
end)
|
|
1041
|
+
|
|
1042
|
+
it("should kill the brio of an item removed after its add has fired", function()
|
|
1043
|
+
local maid = Maid.new()
|
|
1044
|
+
local list = maid:Add(ObservableSortedList.new())
|
|
1045
|
+
|
|
1046
|
+
local remove = list:Add("a", 1)
|
|
1047
|
+
list:_testForceFireEvents()
|
|
1048
|
+
|
|
1049
|
+
local brios: { any } = {}
|
|
1050
|
+
maid:GiveTask(list:ObserveItemsBrio():Subscribe(function(brio)
|
|
1051
|
+
table.insert(brios, brio)
|
|
1052
|
+
end))
|
|
1053
|
+
|
|
1054
|
+
expect(#brios).toEqual(1)
|
|
1055
|
+
|
|
1056
|
+
remove()
|
|
1057
|
+
|
|
1058
|
+
expect(brios[1]:IsDead()).toEqual(true)
|
|
1059
|
+
|
|
1060
|
+
maid:Destroy()
|
|
1061
|
+
end)
|
|
1062
|
+
|
|
1063
|
+
it("should not announce an item added and removed before anyone subscribed", function()
|
|
1064
|
+
local maid = Maid.new()
|
|
1065
|
+
local list = maid:Add(ObservableSortedList.new())
|
|
1066
|
+
|
|
1067
|
+
local remove = list:Add("a", 1)
|
|
1068
|
+
remove()
|
|
1069
|
+
|
|
1070
|
+
local brios: { any } = {}
|
|
1071
|
+
maid:GiveTask(list:ObserveItemsBrio():Subscribe(function(brio)
|
|
1072
|
+
table.insert(brios, brio)
|
|
1073
|
+
end))
|
|
1074
|
+
|
|
1075
|
+
list:_testForceFireEvents()
|
|
1076
|
+
|
|
1077
|
+
expect(#brios).toEqual(0)
|
|
1078
|
+
|
|
1079
|
+
maid:Destroy()
|
|
1080
|
+
end)
|
|
1081
|
+
|
|
1082
|
+
it("should announce an item once when subscribing before its add fires", function()
|
|
1083
|
+
local maid = Maid.new()
|
|
1084
|
+
local list = maid:Add(ObservableSortedList.new())
|
|
1085
|
+
|
|
1086
|
+
list:Add("a", 1)
|
|
1087
|
+
|
|
1088
|
+
local brios: { any } = {}
|
|
1089
|
+
maid:GiveTask(list:ObserveItemsBrio():Subscribe(function(brio)
|
|
1090
|
+
table.insert(brios, brio)
|
|
1091
|
+
end))
|
|
1092
|
+
|
|
1093
|
+
expect(#brios).toEqual(1)
|
|
1094
|
+
|
|
1095
|
+
list:_testForceFireEvents()
|
|
1096
|
+
|
|
1097
|
+
expect(#brios).toEqual(1)
|
|
1098
|
+
expect(brios[1]:IsDead()).toEqual(false)
|
|
1099
|
+
|
|
1100
|
+
maid:Destroy()
|
|
1101
|
+
end)
|
|
1102
|
+
|
|
1103
|
+
it("should keep announcing items added after the subscription", function()
|
|
1104
|
+
local maid = Maid.new()
|
|
1105
|
+
local list = maid:Add(ObservableSortedList.new())
|
|
1106
|
+
|
|
1107
|
+
local brios: { any } = {}
|
|
1108
|
+
maid:GiveTask(list:ObserveItemsBrio():Subscribe(function(brio)
|
|
1109
|
+
table.insert(brios, brio)
|
|
1110
|
+
end))
|
|
1111
|
+
|
|
1112
|
+
list:Add("a", 1)
|
|
1113
|
+
list:_testForceFireEvents()
|
|
1114
|
+
|
|
1115
|
+
expect(#brios).toEqual(1)
|
|
1116
|
+
expect((brios[1]:GetValue())).toEqual("a")
|
|
1117
|
+
|
|
1118
|
+
maid:Destroy()
|
|
1119
|
+
end)
|
|
1120
|
+
|
|
1016
1121
|
it("should handle removing during a sort value change", function()
|
|
1017
1122
|
local maid = Maid.new()
|
|
1018
1123
|
local list = maid:Add(ObservableSortedList.new())
|