sassc 1.11.1 → 1.11.2

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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/README.md +3 -2
  4. data/ext/libsass/Makefile.conf +2 -1
  5. data/ext/libsass/appveyor.yml +10 -5
  6. data/ext/libsass/docs/dev-ast-memory.md +223 -0
  7. data/ext/libsass/include/sass/base.h +2 -0
  8. data/ext/libsass/script/bootstrap +7 -4
  9. data/ext/libsass/script/ci-build-libsass +3 -3
  10. data/ext/libsass/script/ci-install-compiler +2 -0
  11. data/ext/libsass/script/ci-report-coverage +2 -1
  12. data/ext/libsass/script/test-leaks.pl +103 -0
  13. data/ext/libsass/src/ast.cpp +621 -495
  14. data/ext/libsass/src/ast.hpp +801 -367
  15. data/ext/libsass/src/ast_def_macros.hpp +5 -5
  16. data/ext/libsass/src/ast_fwd_decl.hpp +312 -14
  17. data/ext/libsass/src/bind.cpp +54 -51
  18. data/ext/libsass/src/bind.hpp +3 -7
  19. data/ext/libsass/src/check_nesting.cpp +117 -120
  20. data/ext/libsass/src/check_nesting.hpp +38 -34
  21. data/ext/libsass/src/color_maps.cpp +3 -3
  22. data/ext/libsass/src/color_maps.hpp +3 -3
  23. data/ext/libsass/src/context.cpp +33 -34
  24. data/ext/libsass/src/context.hpp +12 -14
  25. data/ext/libsass/src/cssize.cpp +200 -228
  26. data/ext/libsass/src/cssize.hpp +49 -49
  27. data/ext/libsass/src/debugger.hpp +260 -241
  28. data/ext/libsass/src/emitter.cpp +6 -6
  29. data/ext/libsass/src/emitter.hpp +7 -7
  30. data/ext/libsass/src/environment.cpp +2 -2
  31. data/ext/libsass/src/environment.hpp +0 -2
  32. data/ext/libsass/src/error_handling.cpp +5 -5
  33. data/ext/libsass/src/error_handling.hpp +12 -12
  34. data/ext/libsass/src/eval.cpp +412 -401
  35. data/ext/libsass/src/eval.hpp +61 -62
  36. data/ext/libsass/src/expand.cpp +223 -204
  37. data/ext/libsass/src/expand.hpp +42 -42
  38. data/ext/libsass/src/extend.cpp +198 -201
  39. data/ext/libsass/src/extend.hpp +12 -14
  40. data/ext/libsass/src/file.hpp +4 -5
  41. data/ext/libsass/src/functions.cpp +413 -418
  42. data/ext/libsass/src/functions.hpp +7 -10
  43. data/ext/libsass/src/inspect.cpp +115 -109
  44. data/ext/libsass/src/inspect.hpp +69 -69
  45. data/ext/libsass/src/listize.cpp +31 -33
  46. data/ext/libsass/src/listize.hpp +8 -10
  47. data/ext/libsass/src/memory/SharedPtr.cpp +116 -0
  48. data/ext/libsass/src/memory/SharedPtr.hpp +202 -0
  49. data/ext/libsass/src/node.cpp +45 -43
  50. data/ext/libsass/src/node.hpp +15 -15
  51. data/ext/libsass/src/operation.hpp +136 -136
  52. data/ext/libsass/src/output.cpp +48 -49
  53. data/ext/libsass/src/output.hpp +14 -14
  54. data/ext/libsass/src/parser.cpp +530 -554
  55. data/ext/libsass/src/parser.hpp +91 -96
  56. data/ext/libsass/src/prelexer.cpp +13 -10
  57. data/ext/libsass/src/remove_placeholders.cpp +25 -21
  58. data/ext/libsass/src/remove_placeholders.hpp +7 -7
  59. data/ext/libsass/src/sass2scss.cpp +2 -1
  60. data/ext/libsass/src/sass_context.cpp +125 -107
  61. data/ext/libsass/src/sass_context.hpp +1 -1
  62. data/ext/libsass/src/sass_util.hpp +5 -5
  63. data/ext/libsass/src/sass_values.cpp +27 -27
  64. data/ext/libsass/src/source_map.cpp +2 -2
  65. data/ext/libsass/src/source_map.hpp +2 -2
  66. data/ext/libsass/src/subset_map.cpp +57 -0
  67. data/ext/libsass/src/subset_map.hpp +8 -76
  68. data/ext/libsass/src/to_c.cpp +13 -13
  69. data/ext/libsass/src/to_c.hpp +14 -14
  70. data/ext/libsass/src/to_value.cpp +20 -20
  71. data/ext/libsass/src/to_value.hpp +20 -21
  72. data/ext/libsass/src/util.cpp +55 -88
  73. data/ext/libsass/src/util.hpp +9 -13
  74. data/ext/libsass/src/values.cpp +27 -26
  75. data/ext/libsass/src/values.hpp +2 -2
  76. data/ext/libsass/test/test_subset_map.cpp +69 -69
  77. data/ext/libsass/win/libsass.targets +3 -2
  78. data/ext/libsass/win/libsass.vcxproj.filters +9 -6
  79. data/lib/sassc/version.rb +1 -1
  80. data/sassc.gemspec +0 -1
  81. data/test/native_test.rb +1 -1
  82. metadata +7 -5
  83. data/ext/libsass/src/ast_factory.hpp +0 -92
  84. data/ext/libsass/src/memory_manager.cpp +0 -77
  85. data/ext/libsass/src/memory_manager.hpp +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2003bd0fdc35ac8281c0f203771b9e88e3554ce6
4
- data.tar.gz: 4181ece117d80e29ff8abf55805fc8e7710e3c3f
3
+ metadata.gz: 4b738b9d16e9e4b192dd5648204b01388b12d1e2
4
+ data.tar.gz: 83c05efa8d19833ef97ca727bba32441de3ea154
5
5
  SHA512:
6
- metadata.gz: 44ff8a7c1c903405f2124f670b5277fee9f47bd4f61c5c429524b1812a8c3497fd1f4c0ca6812bc886b4414bdeb70846f3a69aef2d0cfd124c5cc30c2e332773
7
- data.tar.gz: cc5690cb269eaa0408ae7c5b6f72aa71b11530357a72b930f3bfcae95ef56df708b97ba1a0c7af6e806802479023e4a306e22ae3758fac656bec84dbb270b494
6
+ metadata.gz: f6a44d53f4bd75fd8c9ad74051d89d41bbd9b8920715895ec501c3ee1ce5cf7b54bb056623d59b7e52e2c49ad59a27be3486e0d2c087453a4cafb5b16d19e4b4
7
+ data.tar.gz: 9afe2183443c33e38313d41d43d8072b39bb78057bdd47e75455288311b140604d819e1d7900b301a2712f4752f1944fbc29d226732a3a6458458765ced549d9
@@ -3,8 +3,8 @@ language: ruby
3
3
  bundler_args: "--binstubs --standalone --without documentation --path ../bundle"
4
4
  script: "bundle exec rake test"
5
5
  rvm:
6
- - 2.0.0
7
- - 2.1.5
8
6
  - 2.2.0
7
+ - 2.3.3
8
+ - 2.4.0
9
9
  notifications:
10
10
  email: false
data/README.md CHANGED
@@ -6,7 +6,7 @@ This gem combines the speed of `libsass`, the [Sass C implementation](https://gi
6
6
 
7
7
  ### libsass Version
8
8
 
9
- [3.4.1](https://github.com/sass/libsass/releases/tag/3.4.1)
9
+ [3.4.3](https://github.com/sass/libsass/releases/tag/3.4.3)
10
10
 
11
11
  ## Installation
12
12
 
@@ -48,7 +48,8 @@ This gem is maintained by [Ryan Boland](https://ryanboland.com)
48
48
  and [awesome contributors](https://github.com/bolandrm/sassc-ruby/graphs/contributors).
49
49
 
50
50
  ## Changelog
51
-
51
+ - **1.11.2**
52
+ - [Update to libsass 3.4.3](https://github.com/sass/sassc-ruby/pull/65)
52
53
  - **1.11.1**
53
54
  - [Update to libsass 3.4.1](https://github.com/sass/sassc-ruby/pull/61)
54
55
  - **1.11.0**
@@ -43,8 +43,9 @@ SOURCES = \
43
43
  to_c.cpp \
44
44
  to_value.cpp \
45
45
  source_map.cpp \
46
+ subset_map.cpp \
46
47
  error_handling.cpp \
47
- memory_manager.cpp \
48
+ memory/SharedPtr.cpp \
48
49
  utf8_string.cpp \
49
50
  base64vlq.cpp
50
51
 
@@ -3,7 +3,7 @@ os: Visual Studio 2013
3
3
  environment:
4
4
  CTEST_OUTPUT_ON_FAILURE: 1
5
5
  ruby_version: 22-x64
6
- TargetPath: sassc/bin/sassc
6
+ TargetPath: sassc/bin/sassc.exe
7
7
  matrix:
8
8
  - Compiler: msvc
9
9
  Config: Release
@@ -63,14 +63,19 @@ test_script:
63
63
  git -C sass-spec checkout -q --force ci-spec-pr-$SPEC_PR
64
64
  }
65
65
  }
66
- ruby sass-spec/sass-spec.rb -V 3.4 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec
67
- if(-not($?)) {
68
- echo "sass-spec tests failed"
66
+ $env:TargetPath = Join-Path $pwd.Path $env:TargetPath
67
+ If (Test-Path "$env:TargetPath") {
68
+ ruby sass-spec/sass-spec.rb -V 3.4 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec
69
+ if(-not($?)) {
70
+ echo "sass-spec tests failed"
71
+ exit 1
72
+ }
73
+ } else {
74
+ echo "spec runner not found (compile error?)"
69
75
  exit 1
70
76
  }
71
77
  Write-Host "Explicitly testing the case when cwd has Cyrillic characters: " -nonewline
72
78
  # See comments in gh-1774 for details.
73
- $env:TargetPath = Join-Path $pwd.Path $env:TargetPath
74
79
  cd sass-spec/spec/libsass/Sáss-UŢF8/
75
80
  &$env:TargetPath ./input.scss 2>&1>$null
76
81
  if(-not($?)) {
@@ -0,0 +1,223 @@
1
+ # LibSass smart pointer implementation
2
+
3
+ LibSass uses smart pointers very similar to `shared_ptr` known
4
+ by Boost or C++11. Implementation is a bit less modular since
5
+ it was not needed. Various compile time debug options are
6
+ available if you need to debug memory life-cycles.
7
+
8
+
9
+ ## Memory Classes
10
+
11
+ ### SharedObj
12
+
13
+ Base class for the actual node implementations. This ensures
14
+ that every object has a reference counter and other values.
15
+
16
+ ```c++
17
+ class AST_Node : public SharedObj { ... };
18
+ ```
19
+
20
+ ### SharedPtr (base class for SharedImpl)
21
+
22
+ Base class that holds on to the pointer. The reference counter
23
+ is stored inside the pointer object directly (`SharedObj`).
24
+
25
+ ### SharedImpl (inherits from SharedPtr)
26
+
27
+ This is the main base class for objects you use in your code. It
28
+ will make sure that the memory it points at will be deleted once
29
+ all copies to the same object/memory go out of scope.
30
+
31
+ ```c++
32
+ Class* pointer = new Class(...);
33
+ SharedImpl<Class> obj(pointer);
34
+ ```
35
+
36
+ To spare the developer of typing the templated class every time,
37
+ we created typedefs for each available AST Node specialization.
38
+
39
+ ```c++
40
+ typedef SharedImpl<Number> Number_Obj;
41
+ Number_Obj number = SASS_MEMORY_NEW(...);
42
+ ```
43
+
44
+
45
+ ## Memory life-cycles
46
+
47
+ ### Pointer pickups
48
+
49
+ I often use the terminology of "pickup". This means the moment when
50
+ a raw pointer not under any control is assigned to a reference counted
51
+ object (`XYZ_Obj = XYZ_Ptr`). From that point on memory will be
52
+ automatically released once the object goes out of scope (but only
53
+ if the reference counter reaches zero). Main point beeing, you don't
54
+ have to worry about memory management yourself.
55
+
56
+ ### Object detach
57
+
58
+ Sometimes we can't return reference counted objects directly (see
59
+ invalid covariant return types problems below). But we often still
60
+ need to use reference objects inside a function to avoid leaks when
61
+ something throws. For this you can use `detach`, which basically
62
+ detaches the pointer memory from the reference counted object. So
63
+ when the reference counted object goes out of scope, it will not
64
+ free the attached memory. You are now again in charge of freeing
65
+ the memory (just assign it to a reference counted object again).
66
+
67
+
68
+ ## Circular references
69
+
70
+ Reference counted memory implementations are prone to circular references.
71
+ This can be addressed by using a multi generation garbage collector. But
72
+ for our use-case that seems overkill. There is no way so far for users
73
+ (sass code) to create circular references. Therefore we can code around
74
+ this possible issue. But developers should be aware of this limitation.
75
+
76
+ There are AFAIR two places where circular references could happen. One is
77
+ the `sources` member on every `Selector`. The other one can happen in the
78
+ extend code (Node handling). The easy way to avoid this is to only assign
79
+ complete object clones to these members. If you know the objects lifetime
80
+ is longer than the reference you create, you can also just store the raw
81
+ pointer. Once needed this could be solved with weak pointers.
82
+
83
+
84
+ ## Addressing the invalid covariant return types problems
85
+
86
+ If you are not familiar with the mentioned problem, you may want
87
+ to read up on covariant return types and virtual functions, i.e.
88
+
89
+ - http://stackoverflow.com/questions/6924754/return-type-covariance-with-smart-pointers
90
+ - http://stackoverflow.com/questions/196733/how-can-i-use-covariant-return-types-with-smart-pointers
91
+ - http://stackoverflow.com/questions/2687790/how-to-accomplish-covariant-return-types-when-returning-a-shared-ptr
92
+
93
+ We hit this issue at least with the CRTP visitor pattern (eval, expand,
94
+ listize and so forth). This means we cannot return reference counted
95
+ objects directly. We are forced to return raw pointers or we would need
96
+ to have a lot of explicit and expensive upcasts by callers/consumers.
97
+
98
+ ### Simple functions that allocate new AST Nodes
99
+
100
+ In the parser step we often create new objects and can just return a
101
+ unique pointer (meaning ownership clearly shifts back to the caller).
102
+ The caller/consumer is responsible that the memory is freed.
103
+
104
+ ```c++
105
+ typedef Number* Number_Ptr;
106
+ int parse_integer() {
107
+ ... // do the parsing
108
+ return 42;
109
+ }
110
+ Number_Ptr parse_number() {
111
+ Number_Ptr p_nr = SASS_MEMORY_NEW(...);
112
+ p_nr->value(parse_integer());
113
+ return p_nr;
114
+ }
115
+ Number_Obj nr = parse_number();
116
+ ```
117
+
118
+ The above would be the encouraged pattern for such simple cases.
119
+
120
+ ### Allocate new AST Nodes in functions that can throw
121
+
122
+ There is a major caveat with the previous example, considering this
123
+ more real-life implementation that throws an error. The throw may
124
+ happen deep down in another function. Holding raw pointers that
125
+ we need to free would leak in this case.
126
+
127
+ ```c++
128
+ int parse_integer() {
129
+ ... // do the parsing
130
+ if (error) throw(error);
131
+ return 42;
132
+ }
133
+ ```
134
+
135
+ With this `parse_integer` function the previous example would leak memory.
136
+ I guess it is pretty obvious, as the allocated memory will not be freed,
137
+ as it was never assigned to a SharedObj value. Therefore the above code
138
+ would better be written as:
139
+
140
+ ```c++
141
+ typedef Number* Number_Ptr;
142
+ int parse_integer() {
143
+ ... // do the parsing
144
+ if (error) throw(error);
145
+ return 42;
146
+ }
147
+ // this leaks due to pointer return
148
+ // should return Number_Obj instead
149
+ // though not possible for virtuals!
150
+ Number_Ptr parse_number() {
151
+ Number_Obj nr = SASS_MEMORY_NEW(...);
152
+ nr->value(parse_integer()); // throws
153
+ return &nr; // Ptr from Obj
154
+ }
155
+ Number_Obj nr = parse_number();
156
+ // will now be freed automatically
157
+ ```
158
+
159
+ The example above unfortunately will not work as is, since we return a
160
+ `Number_Ptr` from that function. Therefore the object allocated inside
161
+ the function is already gone when it is picked up again by the caller.
162
+ The easy fix for the given simplified use case would be to change the
163
+ return type of `parse_number` to `Number_Obj`. Indeed we do it exactly
164
+ this way in the parser. But as stated above, this will not work for
165
+ virtual functions due to invalid covariant return types!
166
+
167
+ ### Return managed objects from virtual functions
168
+
169
+ The easy fix would be to just create a new copy on the heap and return
170
+ that. But this seems like a very inelegant solution to this problem. I
171
+ mean why can't we just tell the object to treat it like a newly allocated
172
+ object? And indeed we can. I've added a `detach` method that will tell
173
+ the object to survive deallocation until the next pickup. This means
174
+ that it will leak if it is not picked up by consumer.
175
+
176
+ ```c++
177
+ typedef Number* Number_Ptr;
178
+ int parse_integer() {
179
+ ... // do the parsing
180
+ if (error) throw(error);
181
+ return 42;
182
+ }
183
+ Number_Ptr parse_number() {
184
+ Number_Obj nr = SASS_MEMORY_NEW(...);
185
+ nr->value(parse_integer()); // throws
186
+ return nr.detach();
187
+ }
188
+ Number_Obj nr = parse_number();
189
+ // will now be freed automatically
190
+ ```
191
+
192
+
193
+ ## Compile time debug options
194
+
195
+ To enable memory debugging you need to define `DEBUG_SHARED_PTR`.
196
+ This can i.e. be done in `include/sass/base.h`
197
+
198
+ ```c++
199
+ define DEBUG_SHARED_PTR
200
+ ```
201
+
202
+ This will print lost memory on exit to stderr. You can also use
203
+ `setDbg(true)` on sepecific variables to emit reference counter
204
+ increase, decrease and other events.
205
+
206
+
207
+ ## Why reinvent the wheel when there is `shared_ptr` from C++11
208
+
209
+ First, implementing a smart pointer class is not really that hard. It
210
+ was indeed also a learning experience for myself. But there are more
211
+ profound advantages:
212
+
213
+ - Better GCC 4.4 compatibility (which most code still has OOTB)
214
+ - Not thread safe (give us some free performance on some compiler)
215
+ - Beeing able to track memory allocations for debugging purposes
216
+ - Adding additional features if needed (as seen in `detach`)
217
+ - Optional: optimized weak pointer implementation possible
218
+
219
+ ### Thread Safety
220
+
221
+ As said above, this is not thread safe currently. But we don't need
222
+ this ATM anyway. And I guess we probably never will share AST Nodes
223
+ across different threads.
@@ -1,6 +1,8 @@
1
1
  #ifndef SASS_BASE_H
2
2
  #define SASS_BASE_H
3
3
 
4
+ // #define DEBUG_SHARED_PTR
5
+
4
6
  #ifdef _MSC_VER
5
7
  #pragma warning(disable : 4503)
6
8
  #ifndef _SCL_SECURE_NO_WARNINGS
@@ -2,9 +2,12 @@
2
2
 
3
3
  script/branding
4
4
 
5
- if [ ! -d "sass-spec" ]; then
6
- git clone https://github.com/sass/sass-spec.git
5
+ : ${SASS_SPEC_PATH:="sass-spec"}
6
+ : ${SASS_SASSC_PATH:="sassc" }
7
+
8
+ if [ ! -d $SASS_SPEC_PATH ]; then
9
+ git clone https://github.com/sass/sass-spec.git $SASS_SPEC_PATH
7
10
  fi
8
- if [ ! -d "sassc" ]; then
9
- git clone https://github.com/sass/sassc.git
11
+ if [ ! -d $SASS_SASSC_PATH ]; then
12
+ git clone https://github.com/sass/sassc.git $SASS_SASSC_PATH
10
13
  fi
@@ -120,10 +120,10 @@ then
120
120
  echo "Fetching Sass Spec PR $SPEC_PR"
121
121
  git -C sass-spec fetch -u origin pull/$SPEC_PR/head:ci-spec-pr-$SPEC_PR
122
122
  git -C sass-spec checkout --force ci-spec-pr-$SPEC_PR
123
- LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_build
123
+ LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_probe
124
124
  else
125
- LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_build
125
+ LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_probe
126
126
  fi
127
127
  else
128
- LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_build
128
+ LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_probe
129
129
  fi
@@ -2,3 +2,5 @@
2
2
 
3
3
  gem install minitest
4
4
  gem install minitap
5
+
6
+ pip install --user 'requests[security]'
@@ -3,7 +3,8 @@
3
3
  if [ "x$COVERAGE" = "xyes" ]; then
4
4
 
5
5
  # exclude some directories from profiling (.libs is from autotools)
6
- export EXCLUDE_COVERAGE="--exclude src/sassc
6
+ export EXCLUDE_COVERAGE="--exclude plugins
7
+ --exclude sassc/sassc.c
7
8
  --exclude src/sass-spec
8
9
  --exclude src/.libs
9
10
  --exclude src/debug.hpp
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/perl
2
+ ############################################################
3
+ # this perl script is meant for developers only!
4
+ # it will run all spec-tests (without verifying the
5
+ # results) via valgrind to detect possible leaks.
6
+ # expect that it takes 1h or more to finish!
7
+ ############################################################
8
+ # Prerequisite install: `cpan Parallel::Runner`
9
+ # You may also need to install `cpan File::Find`
10
+ # You may also need to install `cpan IPC::Run3`
11
+ ############################################################
12
+ # usage: `perl test-leaks.pl [threads]`
13
+ # example: `time perl test-leaks.pl 4`
14
+ ############################################################
15
+ # leaks will be reported in "mem-leaks.log"
16
+ ############################################################
17
+
18
+ use strict;
19
+ use warnings;
20
+
21
+ ############################################################
22
+ # configurations (you may adjust)
23
+ ############################################################
24
+
25
+ # number of threads to use
26
+ my $threads = $ARGV[0] || 8;
27
+
28
+ # the github repositories to checkout
29
+ # if you need other branch, clone manually!
30
+ my $sassc = "https://www.github.com/sass/sassc";
31
+ my $specs = "https://www.github.com/sass/sass-spec";
32
+
33
+ ############################################################
34
+ # load modules
35
+ ############################################################
36
+
37
+ use IPC::Run3;
38
+ use IO::Handle;
39
+ use Fcntl qw(:flock);
40
+ use File::Find::Rule;
41
+ use Parallel::Runner;
42
+ use List::Util qw(shuffle);
43
+
44
+ ############################################################
45
+ # check prerequisites
46
+ ############################################################
47
+
48
+ unless (-d "../sassc") {
49
+ warn "sassc folder not found\n";
50
+ warn "trying to checkout via git\n";
51
+ system("git", "clone", $sassc, "../sassc");
52
+ die "git command did not exit gracefully" if $?;
53
+ }
54
+
55
+ unless (-d "../sass-spec") {
56
+ warn "sass-spec folder not found\n";
57
+ warn "trying to checkout via git\n";
58
+ system("git", "clone", $specs, "../sass-spec");
59
+ die "git command did not exit gracefully" if $?;
60
+ }
61
+
62
+ unless (-f "../sassc/bin/sassc") {
63
+ warn "sassc executable not found\n";
64
+ warn "trying to compile via make\n";
65
+ system("make", "-C", "../sassc", "-j", $threads);
66
+ die "make command did not exit gracefully" if $?;
67
+ }
68
+
69
+ ############################################################
70
+ # main runner code
71
+ ############################################################
72
+
73
+ my $root = "../sass-spec/spec";
74
+ my @files = File::Find::Rule->file()
75
+ ->name('input.scss')->in($root);
76
+
77
+ open(my $leaks, ">", "mem-leaks.log");
78
+ die "Cannot open log" unless $leaks;
79
+ my $runner = Parallel::Runner->new($threads);
80
+ die "Cannot start runner" unless $runner;
81
+
82
+ print "##########################\n";
83
+ print "Testing $#files spec files\n";
84
+ print "##########################\n";
85
+
86
+ foreach my $file (shuffle @files) {
87
+ $runner->run(sub {
88
+ $| = 1; select STDOUT;
89
+ my $cmd = sprintf('../sassc/bin/sassc %s', $file);
90
+ my $check = sprintf('valgrind --leak-check=yes %s', $cmd);
91
+ run3($check, undef, \ my $out, \ my $err);
92
+ if ($err =~ m/in use at exit: 0 bytes in 0 blocks/) {
93
+ print "."; # print success indicator
94
+ } else {
95
+ print "F"; # print error indicator
96
+ flock($leaks, LOCK_EX) or die "Cannot lock log";
97
+ $leaks->printflush("#" x 80, "\n", $err, "\n");
98
+ flock($leaks, LOCK_UN) or die "Cannot unlock log";
99
+ }
100
+ });
101
+ }
102
+
103
+ $runner->finish;