Super speed boost! Like, I'm talking ZOOM! The patch was written by Tom Bagby and modified by myself to make it a bit leaner. The basic idea is that instead of caching the compiled template as a string of Ruby code, we cache it as a compiled method. This means that caching doesn't have to be done Template-side, which also means the :precompiled option now doesn't do anything. I don't think anyone used it anyway, though, so we're all good.
git-svn-id: svn://hamptoncatlin.com/haml/trunk@504 7063305b-7217-0410-af8c-cdc13e5119b9
This commit is contained in:
parent
568051434c
commit
3736c8b7e9
|
@ -635,10 +635,6 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
||||||
# evaluated. If this is true, said scripts are
|
# evaluated. If this is true, said scripts are
|
||||||
# rendered as empty strings. Defaults to false.
|
# rendered as empty strings. Defaults to false.
|
||||||
#
|
#
|
||||||
# [<tt>:precompiled</tt>] A string containing a precompiled Haml template.
|
|
||||||
# If this is passed, <tt>template</tt> is ignored
|
|
||||||
# and no precompilation is done.
|
|
||||||
#
|
|
||||||
# [<tt>:attr_wrapper</tt>] The character that should wrap element attributes.
|
# [<tt>:attr_wrapper</tt>] The character that should wrap element attributes.
|
||||||
# This defaults to <tt>'</tt> (an apostrophe). Characters
|
# This defaults to <tt>'</tt> (an apostrophe). Characters
|
||||||
# of this type within the attributes will be escaped
|
# of this type within the attributes will be escaped
|
||||||
|
|
|
@ -151,8 +151,6 @@ END
|
||||||
end
|
end
|
||||||
@options[:filters].rec_merge! options[:filters] if options[:filters]
|
@options[:filters].rec_merge! options[:filters] if options[:filters]
|
||||||
|
|
||||||
@precompiled = @options[:precompiled]
|
|
||||||
|
|
||||||
@template = template.strip #String
|
@template = template.strip #String
|
||||||
@to_close_stack = []
|
@to_close_stack = []
|
||||||
@output_tabs = 0
|
@output_tabs = 0
|
||||||
|
@ -166,7 +164,7 @@ END
|
||||||
begin
|
begin
|
||||||
# Only do the first round of pre-compiling if we really need to.
|
# Only do the first round of pre-compiling if we really need to.
|
||||||
# They might be passing in the precompiled string.
|
# They might be passing in the precompiled string.
|
||||||
do_precompile if @precompiled.nil? && (@precompiled = String.new)
|
do_precompile unless @@method_names[@template]
|
||||||
rescue Haml::Error => e
|
rescue Haml::Error => e
|
||||||
e.add_backtrace_entry(@index, @options[:filename])
|
e.add_backtrace_entry(@index, @options[:filename])
|
||||||
raise e
|
raise e
|
||||||
|
@ -185,6 +183,12 @@ END
|
||||||
# Compile the @precompiled buffer
|
# Compile the @precompiled buffer
|
||||||
compile &block
|
compile &block
|
||||||
|
|
||||||
|
if @buffer.buffer.empty?
|
||||||
|
if @options[:filename]
|
||||||
|
raise @template.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Return the result string
|
# Return the result string
|
||||||
@buffer.buffer
|
@buffer.buffer
|
||||||
end
|
end
|
||||||
|
@ -195,8 +199,10 @@ END
|
||||||
|
|
||||||
#Precompile each line
|
#Precompile each line
|
||||||
def do_precompile
|
def do_precompile
|
||||||
|
@precompiled = ''
|
||||||
|
method_name = assign_method_name(@template, options[:filename])
|
||||||
push_silent <<-END
|
push_silent <<-END
|
||||||
def _haml_render
|
def #{method_name}
|
||||||
@haml_is_haml = true
|
@haml_is_haml = true
|
||||||
_hamlout = @haml_stack[-1]
|
_hamlout = @haml_stack[-1]
|
||||||
_erbout = _hamlout.buffer
|
_erbout = _hamlout.buffer
|
||||||
|
@ -369,6 +375,22 @@ END
|
||||||
line && line.length > 1 && line[-1] == MULTILINE_CHAR_VALUE && line[-2] == 32
|
line && line.length > 1 && line[-1] == MULTILINE_CHAR_VALUE && line[-2] == 32
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Method for generating compiled method names basically ripped out of ActiveView::Base
|
||||||
|
# If Haml is to be used as a standalone module without rails and still use the precompiled
|
||||||
|
# methods technique, it will end up duplicating this stuff. I can't decide whether
|
||||||
|
# checking compile times to decide whether to recompile a template belongs in here or
|
||||||
|
# out in template.rb
|
||||||
|
@@method_names = {}
|
||||||
|
@@render_method_count = 0
|
||||||
|
def assign_method_name(template, file_name)
|
||||||
|
@@render_method_count += 1
|
||||||
|
@@method_names[template] = "_render_haml_#{@@render_method_count}".intern
|
||||||
|
end
|
||||||
|
|
||||||
|
module CompiledTemplates
|
||||||
|
# holds compiled template code
|
||||||
|
end
|
||||||
|
|
||||||
# Takes <tt>@precompiled</tt>, a string buffer of Ruby code, and
|
# Takes <tt>@precompiled</tt>, a string buffer of Ruby code, and
|
||||||
# evaluates it in the context of <tt>@scope_object</tt>, after preparing
|
# evaluates it in the context of <tt>@scope_object</tt>, after preparing
|
||||||
# <tt>@scope_object</tt>. The code in <tt>@precompiled</tt> populates
|
# <tt>@scope_object</tt>. The code in <tt>@precompiled</tt> populates
|
||||||
|
@ -385,11 +407,21 @@ END
|
||||||
attr :haml_lineno # :nodoc:
|
attr :haml_lineno # :nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@scope_object.class.instance_eval do
|
||||||
|
include CompiledTemplates
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Evaluate the buffer in the context of the scope object
|
if false#options[:filename]
|
||||||
@scope_object.instance_eval @precompiled
|
method_name = @@method_names[options[:filename]]
|
||||||
@scope_object._haml_render &block
|
else
|
||||||
|
method_name = @@method_names[@template]
|
||||||
|
end
|
||||||
|
|
||||||
|
unless @scope_object.respond_to?(method_name)
|
||||||
|
CompiledTemplates.module_eval @precompiled
|
||||||
|
end
|
||||||
|
@scope_object.send(method_name, &block)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
class << e
|
class << e
|
||||||
include Haml::Error
|
include Haml::Error
|
||||||
|
|
|
@ -40,7 +40,6 @@ module Haml
|
||||||
# to render its templates.
|
# to render its templates.
|
||||||
def initialize(view)
|
def initialize(view)
|
||||||
@view = view
|
@view = view
|
||||||
@@precompiled_templates ||= {}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Renders the file at the location <tt>template</tt>,
|
# Renders the file at the location <tt>template</tt>,
|
||||||
|
@ -60,13 +59,7 @@ module Haml
|
||||||
engine = Haml::Engine.new(template, options)
|
engine = Haml::Engine.new(template, options)
|
||||||
else
|
else
|
||||||
options[:filename] ||= template
|
options[:filename] ||= template
|
||||||
if @precompiled = get_precompiled(template)
|
|
||||||
options[:precompiled] ||= @precompiled
|
|
||||||
engine = Haml::Engine.new("", options)
|
|
||||||
else
|
|
||||||
engine = Haml::Engine.new(File.read(template), options)
|
engine = Haml::Engine.new(File.read(template), options)
|
||||||
set_precompiled(template, engine.precompiled)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
yield_proc = @view.instance_eval do
|
yield_proc = @view.instance_eval do
|
||||||
|
@ -76,24 +69,6 @@ module Haml
|
||||||
engine.to_html(@view) { |*args| yield_proc.call(*args) }
|
engine.to_html(@view) { |*args| yield_proc.call(*args) }
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Gets the cached, precompiled version of the template at location <tt>filename</tt>
|
|
||||||
# as a string.
|
|
||||||
def get_precompiled(filename)
|
|
||||||
# Do we have it on file? Is it new enough?
|
|
||||||
if (precompiled, precompiled_on = @@precompiled_templates[filename]) &&
|
|
||||||
(precompiled_on == File.mtime(filename).to_i)
|
|
||||||
precompiled
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sets the cached, precompiled version of the template at location <tt>filename</tt>
|
|
||||||
# to <tt>precompiled</tt>.
|
|
||||||
def set_precompiled(filename, precompiled)
|
|
||||||
@@precompiled_templates[filename] = [precompiled, File.mtime(filename).to_i]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -81,23 +81,6 @@ class EngineTest < Test::Unit::TestCase
|
||||||
assert_equal("<p>Paragraph!</p>\n", render("%p= text", :locals => { :text => "Paragraph!" }))
|
assert_equal("<p>Paragraph!</p>\n", render("%p= text", :locals => { :text => "Paragraph!" }))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_precompiled
|
|
||||||
precompiled = <<-END
|
|
||||||
def _haml_render
|
|
||||||
_hamlout = @haml_stack[-1]
|
|
||||||
_erbout = _hamlout.buffer
|
|
||||||
|
|
||||||
_hamlout.open_tag("p", 0, nil, true, "", nil, nil, false)
|
|
||||||
@haml_lineno = 1
|
|
||||||
haml_temp = "Haml Rocks Socks"
|
|
||||||
haml_temp = _hamlout.push_script(haml_temp, 1, false)
|
|
||||||
_hamlout.close_tag("p", 0)
|
|
||||||
end
|
|
||||||
END
|
|
||||||
|
|
||||||
assert_equal("<p>Haml Rocks Socks</p>\n", render("%h1 I shall not be rendered", :precompiled => precompiled))
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_comps
|
def test_comps
|
||||||
assert_equal(-1, "foo" <=> nil)
|
assert_equal(-1, "foo" <=> nil)
|
||||||
assert_equal(1, nil <=> "foo")
|
assert_equal(1, nil <=> "foo")
|
||||||
|
|
Loading…
Reference in New Issue