haml-edge 3.1.18 → 3.1.19

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.
data/EDGE_GEM_VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.18
1
+ 3.1.19
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.18
1
+ 3.1.19
data/lib/haml/exec.rb CHANGED
@@ -23,7 +23,8 @@ module Haml
23
23
  rescue Exception => e
24
24
  raise e if @options[:trace] || e.is_a?(SystemExit)
25
25
 
26
- $stderr.puts "#{e.class}: #{e.message}"
26
+ $stderr.print "#{e.class}: " unless e.class == RuntimeError
27
+ $stderr.puts "#{e.message}"
27
28
  $stderr.puts " Use --trace for backtrace."
28
29
  exit 1
29
30
  end
@@ -1,3 +1,5 @@
1
+ require 'set'
2
+
1
3
  module Sass
2
4
  # The lexical environment for SassScript.
3
5
  # This keeps track of variable and mixin definitions.
@@ -24,6 +26,7 @@ module Sass
24
26
  @mixins = {}
25
27
  @parent = parent
26
28
  @stack = [] unless parent
29
+ @mixins_in_use = Set.new unless parent
27
30
  set_var("important", Script::String.new("!important")) unless @parent
28
31
  end
29
32
 
@@ -56,6 +59,7 @@ module Sass
56
59
  else
57
60
  stack.push(frame_info)
58
61
  end
62
+ mixins_in_use << stack.last[:mixin] if stack.last[:mixin] && !stack.last[:prepared]
59
63
  end
60
64
 
61
65
  # Like \{#push\_frame}, but next time a stack frame is pushed,
@@ -68,8 +72,9 @@ module Sass
68
72
 
69
73
  # Pop a stack frame from the mixin/include stack.
70
74
  def pop_frame
71
- stack.pop if stack.last[:prepared]
72
- stack.pop
75
+ stack.pop if stack.last && stack.last[:prepared]
76
+ popped = stack.pop
77
+ mixins_in_use.delete(popped[:mixin]) if popped && popped[:mixin]
73
78
  end
74
79
 
75
80
  # A list of stack frames in the mixin/include stack.
@@ -81,6 +86,13 @@ module Sass
81
86
  @stack ||= @parent.stack
82
87
  end
83
88
 
89
+ # A set of names of mixins currently present in the stack.
90
+ #
91
+ # @return [Set<String>] The mixin names.
92
+ def mixins_in_use
93
+ @mixins_in_use ||= @parent.mixins_in_use
94
+ end
95
+
84
96
  class << self
85
97
  private
86
98
 
data/lib/sass/error.rb CHANGED
@@ -137,7 +137,10 @@ module Sass
137
137
  # @see #sass_backtrace
138
138
  # @return [String]
139
139
  def sass_backtrace_str(default_filename = "an unknown file")
140
- "Syntax error: #{message}" +
140
+ lines = self.message.split("\n")
141
+ msg = lines[0] + lines[1..-1].
142
+ map {|l| "\n" + (" " * "Syntax error: ".size) + l}.join
143
+ "Syntax error: #{msg}" +
141
144
  Haml::Util.enum_with_index(sass_backtrace).map do |entry, i|
142
145
  "\n #{i == 0 ? "on" : "from"} line #{entry[:line]}" +
143
146
  " of #{entry[:filename] || default_filename}" +
@@ -66,6 +66,8 @@ module Sass::Tree
66
66
  # @raise [Sass::SyntaxError] if an incorrect number of arguments was passed
67
67
  # @see Sass::Tree
68
68
  def perform!(environment)
69
+ handle_include_loop!(environment) if environment.mixins_in_use.include?(@name)
70
+
69
71
  original_env = environment
70
72
  original_env.push_frame(:filename => filename, :line => line)
71
73
  original_env.prepare_frame(:mixin => @name)
@@ -93,11 +95,29 @@ END
93
95
 
94
96
  self.children = mixin.tree.map {|c| c.perform(environment)}.flatten
95
97
  rescue Sass::SyntaxError => e
96
- e.modify_backtrace(:mixin => @name, :line => @line)
97
- e.add_backtrace(:line => @line)
98
+ if original_env # Don't add backtrace info if this is an @include loop
99
+ e.modify_backtrace(:mixin => @name, :line => @line)
100
+ e.add_backtrace(:line => @line)
101
+ end
98
102
  raise e
99
103
  ensure
100
- original_env.pop_frame
104
+ original_env.pop_frame if original_env
105
+ end
106
+
107
+ private
108
+
109
+ def handle_include_loop!(environment)
110
+ msg = "An @include loop has been found:"
111
+ mixins = environment.stack.map {|s| s[:mixin]}.compact
112
+ if mixins.size == 2 && mixins[0] == mixins[1]
113
+ raise Sass::SyntaxError.new("#{msg} #{@name} includes itself")
114
+ end
115
+
116
+ mixins << @name
117
+ msg << "\n" << Haml::Util.enum_cons(mixins, 2).map do |m1, m2|
118
+ " #{m1} includes #{m2}"
119
+ end.join("\n")
120
+ raise Sass::SyntaxError.new(msg)
101
121
  end
102
122
  end
103
123
  end
@@ -342,6 +342,63 @@ SASS
342
342
  assert_hash_has(err.sass_backtrace[4], :filename => nil, :mixin => nil, :line => 1)
343
343
  end
344
344
 
345
+ def test_basic_mixin_loop_exception
346
+ render <<SASS
347
+ @mixin foo
348
+ @include foo
349
+ @include foo
350
+ SASS
351
+ assert(false, "Exception not raised")
352
+ rescue Sass::SyntaxError => err
353
+ assert_equal("An @include loop has been found: foo includes itself", err.message)
354
+ assert_hash_has(err.sass_backtrace[0], :mixin => "foo", :line => 2)
355
+ end
356
+
357
+ def test_double_mixin_loop_exception
358
+ render <<SASS
359
+ @mixin foo
360
+ @include bar
361
+ @mixin bar
362
+ @include foo
363
+ @include foo
364
+ SASS
365
+ assert(false, "Exception not raised")
366
+ rescue Sass::SyntaxError => err
367
+ assert_equal(<<MESSAGE.rstrip, err.message)
368
+ An @include loop has been found:
369
+ foo includes bar
370
+ bar includes foo
371
+ MESSAGE
372
+ assert_hash_has(err.sass_backtrace[0], :mixin => "bar", :line => 4)
373
+ assert_hash_has(err.sass_backtrace[1], :mixin => "foo", :line => 2)
374
+ end
375
+
376
+ def test_deep_mixin_loop_exception
377
+ render <<SASS
378
+ @mixin foo
379
+ @include bar
380
+
381
+ @mixin bar
382
+ @include baz
383
+
384
+ @mixin baz
385
+ @include foo
386
+
387
+ @include foo
388
+ SASS
389
+ assert(false, "Exception not raised")
390
+ rescue Sass::SyntaxError => err
391
+ assert_equal(<<MESSAGE.rstrip, err.message)
392
+ An @include loop has been found:
393
+ foo includes bar
394
+ bar includes baz
395
+ baz includes foo
396
+ MESSAGE
397
+ assert_hash_has(err.sass_backtrace[0], :mixin => "baz", :line => 8)
398
+ assert_hash_has(err.sass_backtrace[1], :mixin => "bar", :line => 5)
399
+ assert_hash_has(err.sass_backtrace[2], :mixin => "foo", :line => 2)
400
+ end
401
+
345
402
  def test_exception_css_with_offset
346
403
  opts = {:full_exception => true, :line => 362}
347
404
  render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.18
4
+ version: 3.1.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2010-05-19 00:00:00 -04:00
14
+ date: 2010-05-23 00:00:00 -04:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency