signalize 1.0.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|