curlybars 1.16.1.pre.2 → 1.16.1.pre.3

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: a8897a8516ee71758de87ec45acd0dcf0f177ef5e69470dcbc4e81004f57fb26
4
- data.tar.gz: 5948e415e943ff80c52fa5a756259bdda63b8943c10b77eda9bae650e384fe14
3
+ metadata.gz: e8152eb9d4e5789fce89e656283b0ae7be78799bafcd9755c99d793674a01d9a
4
+ data.tar.gz: 57102435a47d352a31c16d994e36bd61436b777e0e98409355bc31161045a44d
5
5
  SHA512:
6
- metadata.gz: 41f73fbddd332bb54078bd45f74dd9eb93192d8707d943d9f72af8ca29da186ad85935bd5b113ddbe74b1f3084a15431c5a13b1145b57cfd1c2b3215624733b2
7
- data.tar.gz: 3cee5f68d7ad53d3b948395e381f83465da70d7ec74a1cdc7bba37f8598ad212264698e8e675aff6925fb573710ab90cae58fb6e5d608570814c80c61b673fff
6
+ metadata.gz: 797b775e410fff90804ecfad939a0f31add15dc199a4b3221dba6ab4d9ee165134b07c40b90d6e16ea87f331ee80226d9ab0ae28823c8508a0dd7c8c5671a57f
7
+ data.tar.gz: 5b2f6719689b4c047d3fa8a0b31dccd92457d5147eb40a0092331eb7b2f349297bdebd0b15b04702d0808bf154b6bbe69f9c2a7a83ddc71df80aae2fa3dbce0b
@@ -47,8 +47,8 @@ module Curlybars
47
47
 
48
48
  contextual_block&.call(context, schema_adder)
49
49
 
50
- schema = all_methods_without_type.each_with_object({}) do |method, memo|
51
- memo[method] = nil
50
+ schema = all_methods_without_type.to_h do |method|
51
+ [method, nil]
52
52
  end
53
53
 
54
54
  methods_with_type_resolved = all_methods_with_type.transform_values do |type|
@@ -104,12 +104,19 @@ module Curlybars
104
104
  define_method(:as_json) do |*args|
105
105
  return @__as_json if defined?(@__as_json)
106
106
 
107
- @__as_json ||= allowed_methods.each_with_object({}) do |method, hash|
107
+ guard = args.first.is_a?(Hash) ? args.first[:curlybars_guard] : nil
108
+ guard&.enter!
109
+
110
+ @__as_json = allowed_methods.each_with_object({}) do |method, hash|
108
111
  unless self.method(method).arity > 0
109
112
  value = send(method)
110
- hash[method] = value.equal?(self) ? "[circular reference]" : value.as_json
113
+ serialized = value.equal?(self) ? "[circular reference]" : value.as_json(*args)
114
+ guard&.measure(serialized)
115
+ hash[method] = serialized
111
116
  end
112
117
  end
118
+ ensure
119
+ guard&.leave!
113
120
  end
114
121
  end
115
122
 
@@ -205,7 +205,7 @@ module Curlybars
205
205
 
206
206
  eval(eval_source) # rubocop:disable Security/Eval -- eval is the established compilation pattern for the whole engine
207
207
  rescue Curlybars::Error::Render => e
208
- raise if e.id == 'render.timeout' || e.id == 'render.output_too_long'
208
+ raise if e.id == 'render.timeout' || e.id == 'render.output_too_long' || e.id == 'render.nesting_too_deep'
209
209
 
210
210
  ""
211
211
  rescue StandardError
@@ -0,0 +1,35 @@
1
+ module Curlybars
2
+ class SerializationGuard
3
+ def initialize(budget:, depth_limit:)
4
+ @budget = budget
5
+ @depth_limit = depth_limit
6
+ @accumulated = 0
7
+ @depth = 0
8
+ end
9
+
10
+ def enter!
11
+ @depth += 1
12
+ return unless @depth > @depth_limit
13
+
14
+ message = "Serialization nesting too deep (> #{@depth_limit})"
15
+ raise Curlybars::Error::Render.new('nesting_too_deep', message, nil)
16
+ end
17
+
18
+ def leave!
19
+ @depth -= 1
20
+ end
21
+
22
+ def measure(value)
23
+ # Only String leaves are counted: deep-measuring every Hash/Array would
24
+ # mean serializing twice. This under-counts raw hash/array fields; the
25
+ # authoritative ceiling is still SafeBuffer#concat at the output node.
26
+ return unless value.is_a?(String)
27
+
28
+ @accumulated += value.bytesize
29
+ return unless @accumulated > @budget
30
+
31
+ message = "Output too long (> #{@budget} bytes)"
32
+ raise Curlybars::Error::Render.new('output_too_long', message, nil)
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Curlybars
4
- VERSION = '1.16.1.pre.2'
4
+ VERSION = '1.16.1.pre.3'
5
5
  end
data/lib/curlybars.rb CHANGED
@@ -104,6 +104,14 @@ module Curlybars
104
104
  finder.find(target_path, role: role)
105
105
  end
106
106
 
107
+ def serialize(value)
108
+ guard = Curlybars::SerializationGuard.new(
109
+ budget: configuration.output_limit,
110
+ depth_limit: configuration.nesting_limit
111
+ )
112
+ value.to_json(curlybars_guard: guard)
113
+ end
114
+
107
115
  def global_helpers_dependency_tree
108
116
  @global_helpers_dependency_tree ||= begin
109
117
  classes = Curlybars.configuration.global_helpers_provider_classes
@@ -147,6 +155,7 @@ module Curlybars
147
155
  end
148
156
 
149
157
  require 'curlybars/safe_buffer'
158
+ require 'curlybars/serialization_guard'
150
159
  require 'curlybars/configuration'
151
160
  require 'curlybars/rendering_support'
152
161
  require 'curlybars/parser'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curlybars
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.1.pre.2
4
+ version: 1.16.1.pre.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Libo Cannici
@@ -123,6 +123,7 @@ files:
123
123
  - lib/curlybars/railtie.rb
124
124
  - lib/curlybars/rendering_support.rb
125
125
  - lib/curlybars/safe_buffer.rb
126
+ - lib/curlybars/serialization_guard.rb
126
127
  - lib/curlybars/template_handler.rb
127
128
  - lib/curlybars/validation_context.rb
128
129
  - lib/curlybars/version.rb