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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e4f4fc25e9d3e2f4e343a22ecd6bf37daa4628da775f9c5d7709177881c927e
4
- data.tar.gz: e91df598b0d5c11a6f4a803481e3fabb8476e59ac873c6fa8d0e2f57d3851cae
3
+ metadata.gz: d07f1ae6a575b06c9831c5a167f69fcc1432a653a907e1cc4ed392271b297e6c
4
+ data.tar.gz: 053fdbe6ce667fee00b58f3ee910b58a7639b44093508dbdf4cc1bcccf09c488
5
5
  SHA512:
6
- metadata.gz: d9bb28f9f5e35093aaf5567df71a9f8c05edd1467c5788f6afd7a4678790a9bd6a8f08c2296641a9bc7bed8c303da594b17ee308f7b57dcb6754d1bc6a9a7451
7
- data.tar.gz: a85f5867add9ecce1cad3bb7bcc9cd975c69097436ec8d9bfccdc260245aa1c5c93f1031b4aa0337cc144ad5453bc4a67ec71611b8dad850e17481d614b5b5c6
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
@@ -1,12 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- signalize (1.0.1)
4
+ signalize (1.2.0)
5
+ concurrent-ruby (~> 1.2)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
10
  coderay (1.1.3)
11
+ concurrent-ruby (1.2.2)
10
12
  ffi (1.15.5)
11
13
  formatador (1.1.0)
12
14
  guard (2.18.0)
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).
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signalize
4
- VERSION = "1.0.1"
4
+ VERSION = "1.2.0"
5
5
  end
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 class_variablize(name)
10
+ def global_map_accessor(name)
10
11
  define_singleton_method "#{name}" do
11
- class_variable_get("@@#{name}")
12
+ GLOBAL_MAP[name]
12
13
  end
13
14
  define_singleton_method "#{name}=" do |value|
14
- class_variable_set("@@#{name}", value)
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
- @@eval_context = nil
32
- class_variablize :eval_context
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
- @@batched_effect = nil
36
- class_variablize :batched_effect
37
- @@batch_depth = 0
38
- class_variablize :batch_depth
39
- @@batch_iteration = 0
40
- class_variablize :batch_iteration
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
- # @@global_version = 0
47
- # class_variablize :global_version
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
- prevContext = Signalize.eval_context
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 = prevContext
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
- # spec.add_dependency "example-gem", "~> 1.0"
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.1
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-03-09 00:00:00.000000000 Z
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: