signalize 1.0.1 → 1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/Gemfile.lock +3 -1
- data/README.md +21 -4
- data/lib/signalize/version.rb +1 -1
- data/lib/signalize.rb +47 -15
- data/signalize.gemspec +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d07f1ae6a575b06c9831c5a167f69fcc1432a653a907e1cc4ed392271b297e6c
|
4
|
+
data.tar.gz: 053fdbe6ce667fee00b58f3ee910b58a7639b44093508dbdf4cc1bcccf09c488
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f2e7666b585b08d1b9e770cd09e558f44fda4bd76be3a58b3355770116ac7e730563b1fba29d273151797ad5efc4aeee8705d195a9d4a21ece91fc247f8f846
|
7
|
+
data.tar.gz: 0d44bbd6f232bb3c9e8f02d99f4d785826cb6ee885bb6be1c43503657dad1c7bbadbc55dc87a24d58d601e534e61497088d6a817b9aaee47808a28463dd4c6bb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
1
3
|
## [Unreleased]
|
2
4
|
|
5
|
+
## [1.2.0] - 2023-10-03
|
6
|
+
|
7
|
+
- Add `untracked` method (implements #5)
|
8
|
+
- Add `mutation_detected` check for `computed`
|
9
|
+
|
10
|
+
Gem now roughly analogous to `@preact/signals-core` v1.5
|
11
|
+
|
12
|
+
## [1.1.0] - 2023-03-25
|
13
|
+
|
14
|
+
- Provide better signal/computed inspect strings (fixes #1)
|
15
|
+
- Use Concurrent::Map for thread-safe globals (fixes #3)
|
16
|
+
|
17
|
+
## [1.0.1] - 2023-03-08
|
18
|
+
|
19
|
+
- Prevent early returns in effect blocks
|
20
|
+
- Use gem's error class (fixes #2)
|
21
|
+
|
3
22
|
## [1.0.0] - 2023-03-07
|
4
23
|
|
5
24
|
- Initial release
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -54,6 +54,27 @@ counter = signal(0)
|
|
54
54
|
counter.value += 1
|
55
55
|
```
|
56
56
|
|
57
|
+
### `untracked { }`
|
58
|
+
|
59
|
+
In case when you're receiving a callback that can read some signals, but you don't want to subscribe to them, you can use `untracked` to prevent any subscriptions from happening.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
require "signalize"
|
63
|
+
include Signalize::API
|
64
|
+
|
65
|
+
counter = signal(0)
|
66
|
+
effect_count = signal(0)
|
67
|
+
fn = proc { effect_count.value + 1 }
|
68
|
+
|
69
|
+
effect do
|
70
|
+
# Logs the value
|
71
|
+
puts counter.value
|
72
|
+
|
73
|
+
# Whenever this effect is triggered, run `fn` that gives new value
|
74
|
+
effect_count.value = untracked(&fn)
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
57
78
|
### `computed { }`
|
58
79
|
|
59
80
|
You derive computed state by accessing a signal's value within a `computed` block and returning a new value. Every time that signal value is updated, a computed value will likewise be updated. Actually, that's not quite accurate — the computed value only computes when it's read. In this sense, we can call computed values "lazily-evaluated".
|
@@ -248,7 +269,3 @@ This project is intended to be a safe, welcoming space for collaboration, and co
|
|
248
269
|
## License
|
249
270
|
|
250
271
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
251
|
-
|
252
|
-
## Code of Conduct
|
253
|
-
|
254
|
-
Everyone interacting in the Signalize project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/whitefusionhq/signalize/blob/main/CODE_OF_CONDUCT.md).
|
data/lib/signalize/version.rb
CHANGED
data/lib/signalize.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "concurrent"
|
3
4
|
require_relative "signalize/version"
|
4
5
|
|
5
6
|
module Signalize
|
6
7
|
class Error < StandardError; end
|
7
8
|
|
8
9
|
class << self
|
9
|
-
def
|
10
|
+
def global_map_accessor(name)
|
10
11
|
define_singleton_method "#{name}" do
|
11
|
-
|
12
|
+
GLOBAL_MAP[name]
|
12
13
|
end
|
13
14
|
define_singleton_method "#{name}=" do |value|
|
14
|
-
|
15
|
+
GLOBAL_MAP[name] = value
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -20,6 +21,10 @@ module Signalize
|
|
20
21
|
raise Signalize::Error, "Cycle detected"
|
21
22
|
end
|
22
23
|
|
24
|
+
def self.mutation_detected
|
25
|
+
raise Signalize::Error, "Computed cannot have side-effects"
|
26
|
+
end
|
27
|
+
|
23
28
|
RUNNING = 1 << 0
|
24
29
|
NOTIFIED = 1 << 1
|
25
30
|
OUTDATED = 1 << 2
|
@@ -27,24 +32,30 @@ module Signalize
|
|
27
32
|
HAS_ERROR = 1 << 4
|
28
33
|
TRACKING = 1 << 5
|
29
34
|
|
35
|
+
GLOBAL_MAP = Concurrent::Map.new
|
36
|
+
|
30
37
|
# Computed | Effect | nil
|
31
|
-
|
32
|
-
|
38
|
+
global_map_accessor :eval_context
|
39
|
+
self.eval_context = nil
|
40
|
+
|
41
|
+
# Used by `untracked` method
|
42
|
+
global_map_accessor :untracked_depth
|
43
|
+
self.untracked_depth = 0
|
33
44
|
|
34
45
|
# Effects collected into a batch.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
46
|
+
global_map_accessor :batched_effect
|
47
|
+
self.batched_effect = nil
|
48
|
+
global_map_accessor :batch_depth
|
49
|
+
self.batch_depth = 0
|
50
|
+
global_map_accessor :batch_iteration
|
51
|
+
self.batch_iteration = 0
|
41
52
|
|
42
53
|
# NOTE: we have removed the global version optimization for Ruby, due to
|
43
54
|
# the possibility of long-running server processes and the number reaching
|
44
55
|
# a dangerously high integer value.
|
45
56
|
#
|
46
|
-
#
|
47
|
-
#
|
57
|
+
# global_map_accessor :global_version
|
58
|
+
# self.global_version = 0
|
48
59
|
|
49
60
|
Node = Struct.new(
|
50
61
|
:_version,
|
@@ -411,6 +422,8 @@ module Signalize
|
|
411
422
|
end
|
412
423
|
|
413
424
|
def value=(value)
|
425
|
+
Signalize.mutation_detected if Signalize.eval_context.is_a?(Signalize::Computed)
|
426
|
+
|
414
427
|
if value != @value
|
415
428
|
Signalize.cycle_detected if Signalize.batch_iteration > 100
|
416
429
|
|
@@ -436,6 +449,10 @@ module Signalize
|
|
436
449
|
end
|
437
450
|
|
438
451
|
def peek = @value
|
452
|
+
|
453
|
+
def inspect
|
454
|
+
"#<#{self.class} value: #{peek.inspect}>"
|
455
|
+
end
|
439
456
|
end
|
440
457
|
|
441
458
|
class Computed < Signal
|
@@ -477,7 +494,7 @@ module Signalize
|
|
477
494
|
return true
|
478
495
|
end
|
479
496
|
|
480
|
-
|
497
|
+
prev_context = Signalize.eval_context
|
481
498
|
begin
|
482
499
|
Signalize.prepare_sources(self)
|
483
500
|
Signalize.eval_context = self
|
@@ -492,7 +509,7 @@ module Signalize
|
|
492
509
|
@_flags |= HAS_ERROR
|
493
510
|
@_version += 1
|
494
511
|
end
|
495
|
-
Signalize.eval_context =
|
512
|
+
Signalize.eval_context = prev_context
|
496
513
|
Signalize.cleanup_sources(self)
|
497
514
|
@_flags &= ~RUNNING
|
498
515
|
|
@@ -660,6 +677,21 @@ module Signalize
|
|
660
677
|
Signalize.end_batch
|
661
678
|
end
|
662
679
|
end
|
680
|
+
|
681
|
+
def untracked
|
682
|
+
return yield unless Signalize.untracked_depth.zero?
|
683
|
+
|
684
|
+
prev_context = Signalize.eval_context
|
685
|
+
Signalize.eval_context = nil
|
686
|
+
Signalize.untracked_depth += 1
|
687
|
+
|
688
|
+
begin
|
689
|
+
return yield
|
690
|
+
ensure
|
691
|
+
Signalize.untracked_depth -= 1
|
692
|
+
Signalize.eval_context = prev_context
|
693
|
+
end
|
694
|
+
end
|
663
695
|
end
|
664
696
|
|
665
697
|
extend API
|
data/signalize.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
29
|
# Uncomment to register a new dependency of your gem
|
30
|
-
|
30
|
+
spec.add_dependency "concurrent-ruby", "~> 1.2"
|
31
31
|
|
32
32
|
# For more information and examples about making a new gem, check out our
|
33
33
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: signalize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jared White
|
@@ -9,8 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
13
|
-
dependencies:
|
12
|
+
date: 2023-10-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: concurrent-ruby
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.2'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.2'
|
14
28
|
description: A Ruby port of Signals, providing reactive variables, derived computed
|
15
29
|
state, side effect callbacks, and batched updates.
|
16
30
|
email:
|