@quenty/signal 2.4.0 → 3.0.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,17 @@
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
+ # [3.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/signal@2.4.0...@quenty/signal@3.0.0) (2023-10-11)
7
+
8
+
9
+ ### Features
10
+
11
+ * Use GoodSignal only as signal implementation ([4475cab](https://github.com/Quenty/NevermoreEngine/commit/4475cab448564a8cf8e51902e30f5c486bf49ac3))
12
+
13
+
14
+
15
+
16
+
6
17
  # [2.4.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/signal@2.3.0...@quenty/signal@2.4.0) (2023-05-26)
7
18
 
8
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/signal",
3
- "version": "2.4.0",
3
+ "version": "3.0.0",
4
4
  "description": "A simple signal implementation for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -29,5 +29,8 @@
29
29
  "publishConfig": {
30
30
  "access": "public"
31
31
  },
32
- "gitHead": "11058e90e51ea83d3dad6ae9abe59cc19c36b94b"
32
+ "dependencies": {
33
+ "@quenty/loader": "^7.0.0"
34
+ },
35
+ "gitHead": "fdeae46099587019ec5fc15317dc673aed379400"
33
36
  }
@@ -1,27 +1,47 @@
1
- --------------------------------------------------------------------------------
2
- -- Batched Yield-Safe Signal Implementation --
3
- -- This is a Signal class which has effectively identical behavior to a --
4
- -- normal RBXScriptSignal, with the only difference being a couple extra --
5
- -- stack frames at the bottom of the stack trace when an error is thrown. --
6
- -- This implementation caches runner coroutines, so the ability to yield in --
7
- -- the signal handlers comes at minimal extra cost over a naive signal --
8
- -- implementation that either always or never spawns a thread. --
9
- -- --
10
- -- API: --
11
- -- local Signal = require(THIS MODULE) --
12
- -- local sig = Signal.new() --
13
- -- local connection = sig:Connect(function(arg1, arg2, ...) ... end) --
14
- -- sig:Fire(arg1, arg2, ...) --
15
- -- connection:Disconnect() --
16
- -- sig:DisconnectAll() --
17
- -- local arg1, arg2, ... = sig:Wait() --
18
- -- --
19
- -- Licence: --
20
- -- Licenced under the MIT licence. --
21
- -- --
22
- -- Authors: --
23
- -- stravant - July 31st, 2021 - Created the file. --
24
- --------------------------------------------------------------------------------
1
+ --[=[
2
+ Batched Yield-Safe Signal Implementation
3
+
4
+ Lua-side duplication of the [API of events on Roblox objects](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptSignal).
5
+
6
+ Signals are needed for to ensure that for local events objects are passed by
7
+ reference rather than by value where possible, as the BindableEvent objects
8
+ always pass signal arguments by value, meaning tables will be deep copied.
9
+ Roblox's deep copy method parses to a non-lua table compatable format.
10
+
11
+ This class is designed to work both in deferred mode and in regular mode.
12
+ It follows whatever mode is set.
13
+
14
+ ```lua
15
+ local signal = Signal.new()
16
+
17
+ local arg = {}
18
+
19
+ signal:Connect(function(value)
20
+ assert(arg == value, "Tables are preserved when firing a Signal")
21
+ end)
22
+
23
+ signal:Fire(arg)
24
+ ```
25
+
26
+ :::info
27
+ Why this over a direct [BindableEvent]? Well, in this case, the signal
28
+ prevents Roblox from trying to serialize and desialize each table reference
29
+ fired through the BindableEvent.
30
+ :::
31
+
32
+ This is a Signal class which has effectively identical behavior to a
33
+ normal RBXScriptSignal, with the only difference being a couple extra
34
+ stack frames at the bottom of the stack trace when an error is thrown
35
+ This implementation caches runner coroutines, so the ability to yield in
36
+ the signal handlers comes at minimal extra cost over a naive signal
37
+ implementation that either always or never spawns a thread.
38
+
39
+ Author notes:
40
+ stravant - July 31st, 2021 - Created the file.
41
+ Quenty - Auguest 21st, 2023 - Modified to fit Nevermore contract, with Moonwave docs
42
+
43
+ @class Signal
44
+ ]=]
25
45
 
26
46
  -- The currently idle thread to run the next handler on
27
47
  local freeRunnerThread = nil
@@ -100,14 +120,36 @@ setmetatable(Connection, {
100
120
 
101
121
  -- Signal class
102
122
  local Signal = {}
123
+ Signal.ClassName = "Signal"
103
124
  Signal.__index = Signal
104
125
 
126
+ --[=[
127
+ Constructs a new signal.
128
+ @return Signal<T>
129
+ ]=]
105
130
  function Signal.new()
106
131
  return setmetatable({
107
132
  _handlerListHead = false,
108
133
  }, Signal)
109
134
  end
110
135
 
136
+ --[=[
137
+ Returns whether a class is a signal
138
+
139
+ @param value any
140
+ @return boolean
141
+ ]=]
142
+ function Signal.isSignal(value)
143
+ return type(value) == "table"
144
+ and getmetatable(value) == Signal
145
+ end
146
+
147
+ --[=[
148
+ Connect a new handler to the event. Returns a connection object that can be disconnected.
149
+
150
+ @param fn (... T) -> () -- Function handler called when `:Fire(...)` is called
151
+ @return RBXScriptConnection
152
+ ]=]
111
153
  function Signal:Connect(fn)
112
154
  local connection = Connection.new(self, fn)
113
155
  if self._handlerListHead then
@@ -119,16 +161,30 @@ function Signal:Connect(fn)
119
161
  return connection
120
162
  end
121
163
 
122
- -- Disconnect all handlers. Since we use a linked list it suffices to clear the
123
- -- reference to the head handler.
164
+ --[=[
165
+ Disconnects all connected events to the signal.
166
+
167
+ :::info
168
+ Disconnect all handlers. Since we use a linked list it suffices to clear the
169
+ reference to the head handler.
170
+ :::
171
+ ]=]
124
172
  function Signal:DisconnectAll()
125
173
  self._handlerListHead = false
126
174
  end
127
175
 
128
- -- Signal:Fire(...) implemented by running the handler functions on the
129
- -- coRunnerThread, and any time the resulting thread yielded without returning
130
- -- to us, that means that it yielded to the Roblox scheduler and has been taken
131
- -- over by Roblox scheduling, meaning we have to make a new coroutine runner.
176
+ --[=[
177
+ Fire the event with the given arguments. All handlers will be invoked. Handlers follow
178
+
179
+ ::: info
180
+ Signal:Fire(...) is implemented by running the handler functions on the
181
+ coRunnerThread, and any time the resulting thread yielded without returning
182
+ to us, that means that it yielded to the Roblox scheduler and has been taken
183
+ over by Roblox scheduling, meaning we have to make a new coroutine runner.
184
+ :::
185
+
186
+ @param ... T -- Variable arguments to pass to handler
187
+ ]=]
132
188
  function Signal:Fire(...)
133
189
  local item = self._handlerListHead
134
190
  while item do
@@ -144,8 +200,17 @@ function Signal:Fire(...)
144
200
  end
145
201
  end
146
202
 
147
- -- Implement Signal:Wait() in terms of a temporary connection using
148
- -- a Signal:Connect() which disconnects itself.
203
+ --[=[
204
+ Wait for fire to be called, and return the arguments it was given.
205
+
206
+ ::: info
207
+ Signal:Wait() is implemented in terms of a temporary connection using
208
+ a Signal:Connect() which disconnects itself.
209
+ :::
210
+
211
+ @yields
212
+ @return T
213
+ ]=]
149
214
  function Signal:Wait()
150
215
  local waitingCoroutine = coroutine.running()
151
216
  local cn;
@@ -156,8 +221,17 @@ function Signal:Wait()
156
221
  return coroutine.yield()
157
222
  end
158
223
 
159
- -- Implement Signal:Once() in terms of a connection which disconnects
160
- -- itself before running the handler.
224
+ --[=[
225
+ Connect a new, one-time handler to the event. Returns a connection object that can be disconnected.
226
+
227
+ ::: info
228
+ -- Implement Signal:Once() in terms of a connection which disconnects
229
+ -- itself before running the handler.
230
+ :::
231
+
232
+ @param fn (... T) -> () -- One-time function handler called when `:Fire(...)` is called
233
+ @return RBXScriptConnection
234
+ ]=]
161
235
  function Signal:Once(fn)
162
236
  local cn;
163
237
  cn = self:Connect(function(...)
@@ -169,6 +243,12 @@ function Signal:Once(fn)
169
243
  return cn
170
244
  end
171
245
 
246
+ --[=[
247
+ Alias for [DisconnectAll]
248
+
249
+ @function Destroy
250
+ @within Signal
251
+ ]=]
172
252
  Signal.Destroy = Signal.DisconnectAll
173
253
 
174
254
  -- Make signal strict
@@ -30,6 +30,14 @@
30
30
  @class Signal
31
31
  ]=]
32
32
 
33
+ local USE_GOOD_SIGNAL_ONLY = true
34
+
35
+ if USE_GOOD_SIGNAL_ONLY then
36
+ local require = require(script.Parent.loader).load(script)
37
+
38
+ return require("GoodSignal")
39
+ end
40
+
33
41
  local HttpService = game:GetService("HttpService")
34
42
 
35
43
  local ENABLE_TRACEBACK = false
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "node_modules",
3
+ "globIgnorePaths": [ "**/.package-lock.json" ],
4
+ "tree": {
5
+ "$path": { "optional": "../node_modules" }
6
+ }
7
+ }