Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIFO cache #653

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- [Breaking] Removed support for `process_attributes`. Instead, override `__attributes__`, calling `super` with your processed attributes. `__attributes__` receives a single positional argument which is the original attributes hash.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phew! 😥 I thought for a second that you had removed this completely then, and with no alternative 😏

Can I suggest simply renaming __attributes__ to process_attributes, as underscore prefixed methods suggest a private API?


## [1.9.0] 2024-11-24

- Improved documentation
Expand Down
2 changes: 0 additions & 2 deletions bench.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
require_relative "fixtures/page"
require_relative "fixtures/layout"

puts RUBY_DESCRIPTION

a = Example::Page.new.call
# Example::Page.compile
# Example::LayoutComponent.compile
Expand Down
13 changes: 7 additions & 6 deletions lib/phlex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
require "erb"

module Phlex
autoload :BlackHole, "phlex/black_hole"
autoload :Callable, "phlex/callable"
autoload :ConcurrentMap, "phlex/concurrent_map"
autoload :Context, "phlex/context"
autoload :CSV, "phlex/csv"
autoload :DeferredRender, "phlex/deferred_render"
autoload :ElementClobberingGuard, "phlex/element_clobbering_guard"
autoload :Elements, "phlex/elements"
autoload :HTML, "phlex/html"
autoload :FIFO, "phlex/fifo"
autoload :Helpers, "phlex/helpers"
autoload :HTML, "phlex/html"
autoload :SGML, "phlex/sgml"
autoload :SVG, "phlex/svg"
autoload :Unbuffered, "phlex/unbuffered"
autoload :ConcurrentMap, "phlex/concurrent_map"
autoload :BlackHole, "phlex/black_hole"
autoload :CSV, "phlex/csv"
autoload :Callable, "phlex/callable"

# Included in all Phlex exceptions allowing you to match any Phlex error.
# @example Rescue any Phlex error:
Expand All @@ -39,7 +40,7 @@ class NameError < ::NameError
end

# @api private
ATTRIBUTE_CACHE = Phlex::ConcurrentMap.new
ATTRIBUTE_CACHE = Phlex::FIFO.new(20_000_000)
end

if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
Expand Down
6 changes: 3 additions & 3 deletions lib/phlex/elements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ def #{method_name}(**attributes, &block)

if attributes.length > 0 # with attributes
if block # with content block
target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
target << "<#{tag}" << __attributes__(attributes) << ">"
yield_content(&block)
target << "</#{tag}>"
else # without content block
target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << "></#{tag}>"
target << "<#{tag}" << __attributes__(attributes) << "></#{tag}>"
end
else # without attributes
if block # with content block
Expand Down Expand Up @@ -77,7 +77,7 @@ def #{method_name}(**attributes)
target = @_context.target

if attributes.length > 0 # with attributes
target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
target << "<#{tag}" << __attributes__(attributes) << ">"
else # without attributes
target << "<#{tag}>"
end
Expand Down
29 changes: 29 additions & 0 deletions lib/phlex/fifo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

class Phlex::FIFO
def initialize(max_bytesize)
@hash = {}
@mutex = Mutex.new

@bytesize = 0
@max_bytesize = max_bytesize
end

def [](key)
@hash[key]
end

def []=(key, value)
@mutex.synchronize do
old_value = @hash.delete(key)
@hash[key] = value

@bytesize += value.bytesize - (old_value ? old_value.bytesize : 0)

while @bytesize > @max_bytesize
key, value = @hash.shift
@bytesize -= value.bytesize
end
end
end
end
47 changes: 12 additions & 35 deletions lib/phlex/sgml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ def new(*args, **kwargs, &block)
end
end

# @api private
def rendered_at_least_once!
alias_method :__attributes__, :__final_attributes__
alias_method :call, :__final_call__
end

# @api private
def element_method?(method_name)
return false unless instance_methods.include?(method_name)
Expand Down Expand Up @@ -94,15 +88,7 @@ def await(task)
end
end

# Renders the view and returns the buffer. The default buffer is a mutable String.
def call(buffer = +"", context: Phlex::Context.new, view_context: nil, parent: nil, &block)
__final_call__(buffer, context: context, view_context: view_context, parent: parent, &block).tap do
self.class.rendered_at_least_once!
end
end

# @api private
def __final_call__(buffer = +"", context: Phlex::Context.new, view_context: nil, parent: nil, &block)
@_buffer = buffer
@_context = context
@_view_context = view_context
Expand Down Expand Up @@ -362,30 +348,21 @@ def __text__(content)
end

# @api private
def __attributes__(**attributes)
__final_attributes__(**attributes).tap do |buffer|
Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] = buffer.freeze
end
end

# @api private
def __final_attributes__(**attributes)
if respond_to?(:process_attributes)
attributes = process_attributes(**attributes)
end

if attributes[:href]&.start_with?(/\s*javascript:/)
attributes.delete(:href)
end
def __attributes__(attributes)
Phlex::ATTRIBUTE_CACHE[attributes.hash] ||= (
if attributes[:href]&.start_with?(/\s*javascript:/)
attributes.delete(:href)
end

if attributes["href"]&.start_with?(/\s*javascript:/)
attributes.delete("href")
end
if attributes["href"]&.start_with?(/\s*javascript:/)
attributes.delete("href")
end

buffer = +""
__build_attributes__(attributes, buffer: buffer)
buffer = +""
__build_attributes__(attributes, buffer: buffer)

buffer
buffer
)
end

# @api private
Expand Down
19 changes: 0 additions & 19 deletions test/phlex/view/process_attributes.rb

This file was deleted.