freezolite 0.4.0 → 0.6.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: ba7e6d9681a85534191c401f217c1d8f184dc86d1f2ac520972352db9d4b7f47
4
- data.tar.gz: 4f92015d4bb62e597f707dc2fc512730bbeb2c06fc652f6b3b20b9bfaa38379c
3
+ metadata.gz: acdc74401331aa64455f0c39ae90d0e770c458d90c373ed4b295079c60357357
4
+ data.tar.gz: 2bd75df12e02beb4fab14c454264f6512c903155d873fc5e52b182da3be96770
5
5
  SHA512:
6
- metadata.gz: 71499e074c60a508d907b0fa2e983ad870668fa74430bee8fcc06cbe34ed1d591ae5b6f86e9e0d71d2571d963263a8ad028f745c7be01f2d7b733f09d11a03e2
7
- data.tar.gz: fb213aaa5f7677908f65154888cb511883ef3e97a2a59b53a7831c8dfc2e9e3a0e9244e465a09677645fd62e6e3d15c1fa45c6a6c41a227e61b60c1e4eadaf09
6
+ metadata.gz: a2907ed214bafd60f15c43144ecf7529799eb21d060f82ddeea1c05ef06c835ce5ccb71e705f6e861c762f26e5a0f9daf0440091b40095843d5ed17c2426ecb2
7
+ data.tar.gz: 86bcac5bafdabc27728a410b802c6f69ca6bf9481061db49c1fb97241e14859ed4952df85000d1fc5948f3ba46be5f57f1c0d85e7e8bb30c70b021b53ccb0f10
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.6.0 (2025-03-07)
6
+
7
+ - Ruby 3.4 support. ([@palkan][])
8
+
9
+ ## 0.5.0
10
+
11
+ - Add constants freezing via the `# shareable_constant_value: ...` pragma. ([@palkan][])
12
+
5
13
  ## 0.4.0 (2023-08-23)
6
14
 
7
15
  - Upgrade to `require-hooks` 0.2.0. ([@palkan][])
data/README.md CHANGED
@@ -5,7 +5,11 @@
5
5
 
6
6
  Tired of adding `# frozen_string_literals: true` to every file in your project or running `rubocop -A` to make it do that for you? What if I told you that you can just add a single gem to your project and activate this option **for the project's files** automatically (without enabling it globally)?
7
7
 
8
- Freezolite is a gem that turn the `frozen_string_literal` compile option on only for the specified files. Thus, it's like running Ruby with `--enable=frozen-string-literal` but only for the files you own.
8
+ Freezolite is a gem that turns the `frozen_string_literal` compile option on only for the specified files. Thus it's like running Ruby with `--enable=frozen-string-literal` but only for the files you own.
9
+
10
+ > 📖 Read more about the motivation behind this project in ["Freezolite: the magic gem for keeping Ruby literals safely frozen"](https://evilmartians.com/chronicles/freezolite-the-magic-gem-for-keeping-ruby-literals-safely-frozen) post.
11
+
12
+ Freezolite also comes with experimental support for [freezing constants](#freezing-constants).
9
13
 
10
14
  ## Usage
11
15
 
@@ -15,7 +19,7 @@ Add the gem to your Gemfile:
15
19
  gem "freezolite"
16
20
  ```
17
21
 
18
- And drop the following line to your application entry-point **after loading dependencies** and before loading your application code. For example, in Rails, you can put it to `config/application.rb` after the `Bundler.require(...)` call:
22
+ And drop the following line into your application entry-point **after loading dependencies** and before loading your application code. For example, in Rails, you can put it in `config/application.rb` after the `Bundler.require(...)` call:
19
23
 
20
24
  ```ruby
21
25
  # config/application.rb
@@ -40,12 +44,30 @@ Freezolite.setup(
40
44
  )
41
45
  ```
42
46
 
43
- **NOTE**: When using auto mode, the `<project-root>/vendor/bundle` folder is excluded automatically. In manual mode, you may want to exclude it yourself.
47
+ > [!NOTE]
48
+ > When using auto mode, the `<project-root>/vendor/bundle` folder is excluded automatically. In manual mode, you may want to exclude it yourself.
44
49
 
45
50
  ### Using with Bootsnap
46
51
 
47
52
  Freezolite is compatible with Bootsnap. Just make sure you require it **after** Bootsnap. No manual cache invalidation required.
48
53
 
54
+ ### Freezing constants
55
+
56
+ Ruby 3 introduced a new pragma—[`# shareable_constant_value: ...`](https://bugs.ruby-lang.org/issues/17273). It's meant to be used with Ractor-driven applications to easily turn constants into Ractor-shareable objects within a source file. Making Ractor-shareable implies **deep freezing**, thus, we can leverage this pragma to automatically freeze constants!
57
+
58
+ Freezolite can automatically inject this pragma for you (only for matching files, similarly to frozen literals). You need to opt-in to enable this feature:
59
+
60
+ ```ruby
61
+ require "freezolite"
62
+ # You can also specify specific values, such as literal, experimental_copy, etc.
63
+ # Setting to `true` is equal to the `literal` value.
64
+ Freezolite.experimental_freeze_constants = true
65
+ require "freezolite/auto" # or setup manually
66
+ ```
67
+
68
+ > [!NOTE]
69
+ > This feature is considered experimental for the following reasons: 1) the pragma itself is not widely used and we still need to learn how to use it in our applications; 2) unlike `# frozen_string_literal`, this setting is not a compiler option but a parser context switch; thus, we have to use source transform here, and literally add a line to the source file, thus, breaking the line numbers in your stack traces, etc.
70
+
49
71
  ### Supported Ruby versions
50
72
 
51
73
  - Ruby (MRI) >= 2.7.0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Freezolite # :nodoc:
4
- VERSION = "0.4.0"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/freezolite.rb CHANGED
@@ -4,16 +4,32 @@ require "freezolite/version"
4
4
 
5
5
  module Freezolite
6
6
  class << self
7
+ attr_reader :experimental_freeze_constants
8
+
9
+ def experimental_freeze_constants=(val)
10
+ @experimental_freeze_constants = (val == true) ? :literal : val
11
+ end
12
+
7
13
  def setup(patterns:, exclude_patterns: nil)
8
14
  require "require-hooks/setup"
9
15
 
10
16
  ::RequireHooks.around_load(patterns: patterns, exclude_patterns: exclude_patterns) do |path, &block|
11
- was_frozen_string_literal = ::RubyVM::InstructionSequence.compile_option[:frozen_string_literal]
17
+ was_frozen_string_literal = ::RubyVM::InstructionSequence.compile_option[:frozen_string_literal] || false
12
18
  ::RubyVM::InstructionSequence.compile_option = {frozen_string_literal: true}
13
19
  block.call
14
20
  ensure
15
21
  ::RubyVM::InstructionSequence.compile_option = {frozen_string_literal: was_frozen_string_literal}
16
22
  end
23
+
24
+ if experimental_freeze_constants
25
+ val = experimental_freeze_constants
26
+ RequireHooks.source_transform(patterns: patterns, exclude_patterns: exclude_patterns) do |path, source|
27
+ source ||= File.read(path)
28
+ "# shareable_constant_value: #{val}\n#{source}"
29
+ end
30
+ end
17
31
  end
18
32
  end
33
+
34
+ self.experimental_freeze_constants = false
19
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freezolite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-23 00:00:00.000000000 Z
11
+ date: 2025-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: require-hooks
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  requirements: []
106
- rubygems_version: 3.4.8
106
+ rubygems_version: 3.4.19
107
107
  signing_key:
108
108
  specification_version: 4
109
109
  summary: Example description