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 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: