view_component 3.25.0 → 3.27.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 +4 -4
- data/app/helpers/preview_helper.rb +9 -1
- data/docs/CHANGELOG.md +16 -0
- data/lib/view_component/base.rb +17 -2
- data/lib/view_component/collection.rb +10 -5
- data/lib/view_component/compiler.rb +9 -1
- data/lib/view_component/errors.rb +13 -0
- data/lib/view_component/version.rb +1 -1
- metadata +115 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea3b7eaa6244e04ffa83e7c9d4aeafca18230bedcce0fb160b1001b0441270b0
|
|
4
|
+
data.tar.gz: aa605998a6e975f74c307faca61ec6d10b837cdee83c48fe2424e5b6421daf8a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3ec820b42851cb62062972e1473ebb508798e0acd63bfff6e6fda1087c62776806c0199a9e11d6b13bd2914330bf0ad1cb899511c55f62af1538be7a9292a13
|
|
7
|
+
data.tar.gz: 748b43b70dec2efc5319bec3379f6b7cf115789f731e3a32af789c304644d20f14d62c9bc727ab88baa4a52dbeba806f8f403dcee1bcf1bc9a6df6ee73f0d412
|
|
@@ -23,7 +23,7 @@ module PreviewHelper
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def find_template_data_for_preview_source(lookup_context:, template_identifier:)
|
|
26
|
-
template = lookup_context
|
|
26
|
+
template = find_template_for_preview_source(lookup_context, template_identifier)
|
|
27
27
|
|
|
28
28
|
if Rails.version.to_f >= 6.1 || template.source.present?
|
|
29
29
|
{
|
|
@@ -61,6 +61,14 @@ module PreviewHelper
|
|
|
61
61
|
|
|
62
62
|
private
|
|
63
63
|
|
|
64
|
+
def find_template_for_preview_source(lookup_context, template_identifier)
|
|
65
|
+
if lookup_context.respond_to?(:find_template)
|
|
66
|
+
lookup_context.find_template(template_identifier)
|
|
67
|
+
else
|
|
68
|
+
lookup_context.find(template_identifier)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
64
72
|
def prism_language_name_by_template(template:)
|
|
65
73
|
language = template.identifier.split(".").last
|
|
66
74
|
|
data/docs/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,22 @@ nav_order: 6
|
|
|
10
10
|
|
|
11
11
|
## main
|
|
12
12
|
|
|
13
|
+
## 3.27.0
|
|
14
|
+
|
|
15
|
+
* [Security] Fix incomplete remediation for CVE-2026-54497 (GHSA-8qw7-6phv-7q6p): reused ViewComponent instances could still leak `with_content` and `renders_one`/`renders_many` slot content from an earlier render into a later render because slot state and content set via `with_content` are populated by the caller before `render_in` runs and were not cleared by the previous per-render reset. Reinstate the `ViewComponent::ReusedInstanceError` guard that raises when a component instance is rendered more than once. Rebuild collection child components per render and dup collection spacer components before each render so that legitimate re-rendering of `Collection`/spacer objects continues to work.
|
|
16
|
+
|
|
17
|
+
*Yazan Balawneh, Cystack.ps*
|
|
18
|
+
|
|
19
|
+
## 3.26.0
|
|
20
|
+
|
|
21
|
+
* Fix rendering partials from components rendered as a collection when the original view context is explicitly stashed as `nil`.
|
|
22
|
+
|
|
23
|
+
*Justin Coyne, Joel Hawksley*
|
|
24
|
+
|
|
25
|
+
* Restore compatibility with Rails main after `ActionView::Template.template_handler_extensions` and `ActionView::LookupContext#find_template` were removed.
|
|
26
|
+
|
|
27
|
+
*Joel Hawksley*
|
|
28
|
+
|
|
13
29
|
## 3.25.0
|
|
14
30
|
|
|
15
31
|
* Support Rails `render_in` options signature. Rails [#50623](https://github.com/rails/rails/pull/50623) changed the `render_in` signature from `render_in(view_context, &block)` to `render_in(view_context, **options, &block)`. `ViewComponent::Base#render_in`, `ViewComponent::Collection#render_in`, and `ViewComponent::Instrumentation#render_in` now accept `**options`, restoring compatibility with Rails main and silencing the deprecation warning.
|
data/lib/view_component/base.rb
CHANGED
|
@@ -83,12 +83,13 @@ module ViewComponent
|
|
|
83
83
|
def render_in(view_context, **options, &block)
|
|
84
84
|
self.class.compile(raise_errors: true)
|
|
85
85
|
|
|
86
|
+
__vc_check_reused_instance!
|
|
86
87
|
__vc_reset_render_state!
|
|
87
88
|
|
|
88
89
|
@view_context = view_context
|
|
89
90
|
self.__vc_original_view_context =
|
|
90
91
|
if instance_variable_defined?(:@__vc_pending_original_view_context)
|
|
91
|
-
remove_instance_variable(:@__vc_pending_original_view_context)
|
|
92
|
+
remove_instance_variable(:@__vc_pending_original_view_context) || view_context
|
|
92
93
|
else
|
|
93
94
|
view_context
|
|
94
95
|
end
|
|
@@ -137,6 +138,7 @@ module ViewComponent
|
|
|
137
138
|
end
|
|
138
139
|
ensure
|
|
139
140
|
@current_template = old_current_template
|
|
141
|
+
@__vc_rendered = true
|
|
140
142
|
end
|
|
141
143
|
|
|
142
144
|
# Subclass components that call `super` inside their template code will cause a
|
|
@@ -410,7 +412,9 @@ module ViewComponent
|
|
|
410
412
|
# state from a previous render. Slot state (`@__vc_set_slots`,
|
|
411
413
|
# `@__vc_content_set_by_with_content`) is intentionally preserved because it
|
|
412
414
|
# is populated by callers _before_ `render_in` runs (e.g. via `with_*`
|
|
413
|
-
# slot setters or `with_content`)
|
|
415
|
+
# slot setters or `with_content`); reuse of an instance that has slot or
|
|
416
|
+
# `with_content` state is guarded against separately by
|
|
417
|
+
# `__vc_check_reused_instance!`.
|
|
414
418
|
def __vc_reset_render_state!
|
|
415
419
|
%i[
|
|
416
420
|
@__vc_controller
|
|
@@ -422,6 +426,17 @@ module ViewComponent
|
|
|
422
426
|
end
|
|
423
427
|
end
|
|
424
428
|
|
|
429
|
+
# Raises when a component instance is rendered more than once.
|
|
430
|
+
# Reusing a component instance across renders can leak request-scoped state
|
|
431
|
+
# (controller, helpers, request, view_flow, slot content, `with_content`)
|
|
432
|
+
# from an earlier render into a later one. See
|
|
433
|
+
# `ViewComponent::ReusedInstanceError` and GHSA-8qw7-6phv-7q6p.
|
|
434
|
+
def __vc_check_reused_instance!
|
|
435
|
+
return unless defined?(@__vc_rendered) && @__vc_rendered
|
|
436
|
+
|
|
437
|
+
raise ReusedInstanceError.new(self.class.name)
|
|
438
|
+
end
|
|
439
|
+
|
|
425
440
|
# Configuration for generators.
|
|
426
441
|
#
|
|
427
442
|
# All options under this namespace default to `false` unless otherwise
|
|
@@ -72,13 +72,18 @@ module ViewComponent
|
|
|
72
72
|
@options.merge(item_options)
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
# Render the spacer through a fresh `dup` so a collection rendered multiple
|
|
76
|
+
# times does not reuse (and trip the single-render guard on) the spacer
|
|
77
|
+
# instance passed by the caller.
|
|
75
78
|
def rendered_spacer(view_context)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
return "" unless @spacer_component
|
|
80
|
+
|
|
81
|
+
spacer = @spacer_component.dup
|
|
82
|
+
if spacer.instance_variable_defined?(:@__vc_rendered)
|
|
83
|
+
spacer.remove_instance_variable(:@__vc_rendered)
|
|
81
84
|
end
|
|
85
|
+
spacer.set_original_view_context(__vc_original_view_context) if spacer.respond_to?(:set_original_view_context)
|
|
86
|
+
spacer.render_in(view_context)
|
|
82
87
|
end
|
|
83
88
|
end
|
|
84
89
|
end
|
|
@@ -170,7 +170,7 @@ module ViewComponent
|
|
|
170
170
|
@templates ||=
|
|
171
171
|
begin
|
|
172
172
|
templates = @component.sidecar_files(
|
|
173
|
-
|
|
173
|
+
template_handler_extensions
|
|
174
174
|
).map do |path|
|
|
175
175
|
# Extract format and variant from template filename
|
|
176
176
|
this_format, variant =
|
|
@@ -225,5 +225,13 @@ module ViewComponent
|
|
|
225
225
|
templates
|
|
226
226
|
end
|
|
227
227
|
end
|
|
228
|
+
|
|
229
|
+
def template_handler_extensions
|
|
230
|
+
if ActionView::Template.respond_to?(:template_handler_extensions)
|
|
231
|
+
ActionView::Template.template_handler_extensions
|
|
232
|
+
else
|
|
233
|
+
ActionView::Template::Handlers.extensions.map(&:to_s)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
228
236
|
end
|
|
229
237
|
end
|
|
@@ -175,6 +175,19 @@ module ViewComponent
|
|
|
175
175
|
"To fix this issue, pass a value."
|
|
176
176
|
end
|
|
177
177
|
|
|
178
|
+
class ReusedInstanceError < StandardError
|
|
179
|
+
MESSAGE =
|
|
180
|
+
"ViewComponent instances are single-use; a COMPONENT instance was rendered more than once.\n\n" \
|
|
181
|
+
"Reusing a component instance across renders can leak request-scoped state " \
|
|
182
|
+
"(controller, helpers, request, view_flow, slot content, `with_content`) from an earlier render " \
|
|
183
|
+
"into a later one, which has security and correctness implications (GHSA-8qw7-6phv-7q6p).\n\n" \
|
|
184
|
+
"To fix this issue, create a new component instance per render."
|
|
185
|
+
|
|
186
|
+
def initialize(klass_name)
|
|
187
|
+
super(MESSAGE.gsub("COMPONENT", klass_name.to_s))
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
178
191
|
class TranslateCalledBeforeRenderError < BaseError
|
|
179
192
|
MESSAGE =
|
|
180
193
|
"`#translate` can't be used before rendering as it depends " \
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: view_component
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.27.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ViewComponent Team
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -450,8 +449,118 @@ dependencies:
|
|
|
450
449
|
- - "~>"
|
|
451
450
|
- !ruby/object:Gem::Version
|
|
452
451
|
version: 0.0.1
|
|
453
|
-
|
|
454
|
-
|
|
452
|
+
- !ruby/object:Gem::Dependency
|
|
453
|
+
name: net-imap
|
|
454
|
+
requirement: !ruby/object:Gem::Requirement
|
|
455
|
+
requirements:
|
|
456
|
+
- - ">="
|
|
457
|
+
- !ruby/object:Gem::Version
|
|
458
|
+
version: '0'
|
|
459
|
+
type: :development
|
|
460
|
+
prerelease: false
|
|
461
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
462
|
+
requirements:
|
|
463
|
+
- - ">="
|
|
464
|
+
- !ruby/object:Gem::Version
|
|
465
|
+
version: '0'
|
|
466
|
+
- !ruby/object:Gem::Dependency
|
|
467
|
+
name: net-pop
|
|
468
|
+
requirement: !ruby/object:Gem::Requirement
|
|
469
|
+
requirements:
|
|
470
|
+
- - ">="
|
|
471
|
+
- !ruby/object:Gem::Version
|
|
472
|
+
version: '0'
|
|
473
|
+
type: :development
|
|
474
|
+
prerelease: false
|
|
475
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
476
|
+
requirements:
|
|
477
|
+
- - ">="
|
|
478
|
+
- !ruby/object:Gem::Version
|
|
479
|
+
version: '0'
|
|
480
|
+
- !ruby/object:Gem::Dependency
|
|
481
|
+
name: net-smtp
|
|
482
|
+
requirement: !ruby/object:Gem::Requirement
|
|
483
|
+
requirements:
|
|
484
|
+
- - ">="
|
|
485
|
+
- !ruby/object:Gem::Version
|
|
486
|
+
version: '0'
|
|
487
|
+
type: :development
|
|
488
|
+
prerelease: false
|
|
489
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
490
|
+
requirements:
|
|
491
|
+
- - ">="
|
|
492
|
+
- !ruby/object:Gem::Version
|
|
493
|
+
version: '0'
|
|
494
|
+
- !ruby/object:Gem::Dependency
|
|
495
|
+
name: base64
|
|
496
|
+
requirement: !ruby/object:Gem::Requirement
|
|
497
|
+
requirements:
|
|
498
|
+
- - ">="
|
|
499
|
+
- !ruby/object:Gem::Version
|
|
500
|
+
version: '0'
|
|
501
|
+
type: :development
|
|
502
|
+
prerelease: false
|
|
503
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
504
|
+
requirements:
|
|
505
|
+
- - ">="
|
|
506
|
+
- !ruby/object:Gem::Version
|
|
507
|
+
version: '0'
|
|
508
|
+
- !ruby/object:Gem::Dependency
|
|
509
|
+
name: bigdecimal
|
|
510
|
+
requirement: !ruby/object:Gem::Requirement
|
|
511
|
+
requirements:
|
|
512
|
+
- - ">="
|
|
513
|
+
- !ruby/object:Gem::Version
|
|
514
|
+
version: '0'
|
|
515
|
+
type: :development
|
|
516
|
+
prerelease: false
|
|
517
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
518
|
+
requirements:
|
|
519
|
+
- - ">="
|
|
520
|
+
- !ruby/object:Gem::Version
|
|
521
|
+
version: '0'
|
|
522
|
+
- !ruby/object:Gem::Dependency
|
|
523
|
+
name: drb
|
|
524
|
+
requirement: !ruby/object:Gem::Requirement
|
|
525
|
+
requirements:
|
|
526
|
+
- - ">="
|
|
527
|
+
- !ruby/object:Gem::Version
|
|
528
|
+
version: '0'
|
|
529
|
+
type: :development
|
|
530
|
+
prerelease: false
|
|
531
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
532
|
+
requirements:
|
|
533
|
+
- - ">="
|
|
534
|
+
- !ruby/object:Gem::Version
|
|
535
|
+
version: '0'
|
|
536
|
+
- !ruby/object:Gem::Dependency
|
|
537
|
+
name: mutex_m
|
|
538
|
+
requirement: !ruby/object:Gem::Requirement
|
|
539
|
+
requirements:
|
|
540
|
+
- - ">="
|
|
541
|
+
- !ruby/object:Gem::Version
|
|
542
|
+
version: '0'
|
|
543
|
+
type: :development
|
|
544
|
+
prerelease: false
|
|
545
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
546
|
+
requirements:
|
|
547
|
+
- - ">="
|
|
548
|
+
- !ruby/object:Gem::Version
|
|
549
|
+
version: '0'
|
|
550
|
+
- !ruby/object:Gem::Dependency
|
|
551
|
+
name: propshaft
|
|
552
|
+
requirement: !ruby/object:Gem::Requirement
|
|
553
|
+
requirements:
|
|
554
|
+
- - "~>"
|
|
555
|
+
- !ruby/object:Gem::Version
|
|
556
|
+
version: 1.1.0
|
|
557
|
+
type: :development
|
|
558
|
+
prerelease: false
|
|
559
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
560
|
+
requirements:
|
|
561
|
+
- - "~>"
|
|
562
|
+
- !ruby/object:Gem::Version
|
|
563
|
+
version: 1.1.0
|
|
455
564
|
executables: []
|
|
456
565
|
extensions: []
|
|
457
566
|
extra_rdoc_files: []
|
|
@@ -532,7 +641,6 @@ metadata:
|
|
|
532
641
|
allowed_push_host: https://rubygems.org
|
|
533
642
|
source_code_uri: https://github.com/viewcomponent/view_component
|
|
534
643
|
changelog_uri: https://github.com/ViewComponent/view_component/blob/main/docs/CHANGELOG.md
|
|
535
|
-
post_install_message:
|
|
536
644
|
rdoc_options: []
|
|
537
645
|
require_paths:
|
|
538
646
|
- lib
|
|
@@ -547,8 +655,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
547
655
|
- !ruby/object:Gem::Version
|
|
548
656
|
version: '0'
|
|
549
657
|
requirements: []
|
|
550
|
-
rubygems_version: 3.
|
|
551
|
-
signing_key:
|
|
658
|
+
rubygems_version: 3.6.9
|
|
552
659
|
specification_version: 4
|
|
553
660
|
summary: A framework for building reusable, testable & encapsulated view components
|
|
554
661
|
in Ruby on Rails.
|