haml-edge 3.1.18 → 3.1.19

Sign up to get free protection for your applications and to get access to all the features.
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