sassc 1.11.4 → 1.12.0
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.
- checksums.yaml +5 -5
- data/.travis.yml +2 -2
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.md +4 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.github/CONTRIBUTING.md +7 -7
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +37 -18
- data/ext/libsass/GNUmakefile.am +23 -37
- data/ext/libsass/Makefile +10 -6
- data/ext/libsass/Makefile.conf +3 -0
- data/ext/libsass/Readme.md +68 -63
- data/ext/libsass/appveyor.yml +7 -3
- data/ext/libsass/configure.ac +10 -14
- data/ext/libsass/docs/api-context-internal.md +29 -21
- data/ext/libsass/docs/api-context.md +26 -6
- data/ext/libsass/docs/api-doc.md +49 -16
- data/ext/libsass/docs/api-function-example.md +1 -1
- data/ext/libsass/docs/api-function.md +31 -7
- data/ext/libsass/docs/api-importer.md +19 -19
- data/ext/libsass/docs/api-value.md +4 -2
- data/ext/libsass/docs/build-on-windows.md +4 -4
- data/ext/libsass/docs/build-with-mingw.md +3 -3
- data/ext/libsass/docs/build.md +9 -9
- data/ext/libsass/docs/custom-functions-internal.md +10 -8
- data/ext/libsass/docs/implementations.md +20 -8
- data/ext/libsass/docs/unicode.md +16 -10
- data/ext/libsass/include/sass/base.h +0 -3
- data/ext/libsass/include/sass/context.h +20 -2
- data/ext/libsass/include/sass/functions.h +31 -0
- data/ext/libsass/include/sass/values.h +3 -1
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass/version.h.in +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/res/resource.rc +6 -6
- data/ext/libsass/script/ci-build-libsass +10 -5
- data/ext/libsass/script/ci-build-plugin +62 -0
- data/ext/libsass/script/ci-install-compiler +1 -1
- data/ext/libsass/script/ci-install-deps +4 -7
- data/ext/libsass/script/ci-report-coverage +13 -3
- data/ext/libsass/script/tap-driver +1 -1
- data/ext/libsass/script/tap-runner +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -1
- data/ext/libsass/src/ast.cpp +537 -762
- data/ext/libsass/src/ast.hpp +377 -419
- data/ext/libsass/src/ast_def_macros.hpp +26 -1
- data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
- data/ext/libsass/src/b64/encode.h +3 -1
- data/ext/libsass/src/backtrace.cpp +46 -0
- data/ext/libsass/src/backtrace.hpp +7 -54
- data/ext/libsass/src/bind.cpp +72 -50
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/cencode.c +6 -0
- data/ext/libsass/src/check_nesting.cpp +157 -135
- data/ext/libsass/src/check_nesting.hpp +11 -10
- data/ext/libsass/src/color_maps.cpp +10 -6
- data/ext/libsass/src/color_maps.hpp +6 -8
- data/ext/libsass/src/constants.cpp +4 -3
- data/ext/libsass/src/constants.hpp +4 -3
- data/ext/libsass/src/context.cpp +110 -47
- data/ext/libsass/src/context.hpp +11 -1
- data/ext/libsass/src/cssize.cpp +105 -94
- data/ext/libsass/src/cssize.hpp +4 -5
- data/ext/libsass/src/debugger.hpp +247 -244
- data/ext/libsass/src/emitter.cpp +30 -6
- data/ext/libsass/src/emitter.hpp +7 -0
- data/ext/libsass/src/environment.cpp +67 -16
- data/ext/libsass/src/environment.hpp +28 -7
- data/ext/libsass/src/error_handling.cpp +92 -64
- data/ext/libsass/src/error_handling.hpp +64 -43
- data/ext/libsass/src/eval.cpp +494 -544
- data/ext/libsass/src/eval.hpp +17 -23
- data/ext/libsass/src/expand.cpp +182 -154
- data/ext/libsass/src/expand.hpp +4 -5
- data/ext/libsass/src/extend.cpp +299 -291
- data/ext/libsass/src/extend.hpp +46 -11
- data/ext/libsass/src/file.cpp +103 -36
- data/ext/libsass/src/file.hpp +21 -4
- data/ext/libsass/src/functions.cpp +561 -312
- data/ext/libsass/src/functions.hpp +8 -5
- data/ext/libsass/src/inspect.cpp +108 -53
- data/ext/libsass/src/inspect.hpp +5 -2
- data/ext/libsass/src/lexer.cpp +15 -7
- data/ext/libsass/src/lexer.hpp +13 -4
- data/ext/libsass/src/listize.cpp +3 -2
- data/ext/libsass/src/listize.hpp +0 -1
- data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
- data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
- data/ext/libsass/src/node.cpp +34 -38
- data/ext/libsass/src/node.hpp +6 -8
- data/ext/libsass/src/operation.hpp +2 -2
- data/ext/libsass/src/operators.cpp +240 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/output.cpp +22 -20
- data/ext/libsass/src/parser.cpp +719 -358
- data/ext/libsass/src/parser.hpp +57 -22
- data/ext/libsass/src/plugins.cpp +28 -10
- data/ext/libsass/src/position.cpp +21 -3
- data/ext/libsass/src/position.hpp +2 -1
- data/ext/libsass/src/prelexer.cpp +104 -19
- data/ext/libsass/src/prelexer.hpp +10 -3
- data/ext/libsass/src/remove_placeholders.cpp +9 -10
- data/ext/libsass/src/remove_placeholders.hpp +1 -5
- data/ext/libsass/src/sass.cpp +62 -4
- data/ext/libsass/src/sass.hpp +5 -2
- data/ext/libsass/src/sass_context.cpp +96 -58
- data/ext/libsass/src/sass_context.hpp +7 -5
- data/ext/libsass/src/sass_functions.cpp +63 -1
- data/ext/libsass/src/sass_functions.hpp +19 -1
- data/ext/libsass/src/sass_util.cpp +3 -3
- data/ext/libsass/src/sass_util.hpp +4 -4
- data/ext/libsass/src/sass_values.cpp +42 -39
- data/ext/libsass/src/sass_values.hpp +2 -1
- data/ext/libsass/src/source_map.cpp +16 -18
- data/ext/libsass/src/subset_map.cpp +6 -8
- data/ext/libsass/src/subset_map.hpp +6 -6
- data/ext/libsass/src/to_c.cpp +2 -2
- data/ext/libsass/src/to_value.cpp +8 -3
- data/ext/libsass/src/to_value.hpp +1 -0
- data/ext/libsass/src/units.cpp +349 -45
- data/ext/libsass/src/units.hpp +39 -22
- data/ext/libsass/src/utf8/checked.h +7 -0
- data/ext/libsass/src/utf8/unchecked.h +7 -0
- data/ext/libsass/src/utf8_string.cpp +1 -1
- data/ext/libsass/src/util.cpp +139 -45
- data/ext/libsass/src/util.hpp +4 -7
- data/ext/libsass/src/values.cpp +15 -23
- data/ext/libsass/win/libsass.sln +13 -2
- data/ext/libsass/win/libsass.sln.DotSettings +9 -0
- data/ext/libsass/win/libsass.targets +3 -0
- data/ext/libsass/win/libsass.vcxproj.filters +9 -0
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +1 -1
- data/test/native_test.rb +1 -1
- metadata +11 -4
|
@@ -19,12 +19,21 @@ class LocalOption {
|
|
|
19
19
|
this->orig = var;
|
|
20
20
|
*(this->var) = orig;
|
|
21
21
|
}
|
|
22
|
+
void reset()
|
|
23
|
+
{
|
|
24
|
+
*(this->var) = this->orig;
|
|
25
|
+
}
|
|
22
26
|
~LocalOption() {
|
|
23
27
|
*(this->var) = this->orig;
|
|
24
28
|
}
|
|
25
29
|
};
|
|
26
30
|
|
|
27
31
|
#define LOCAL_FLAG(name,opt) LocalOption<bool> flag_##name(name, opt)
|
|
32
|
+
#define LOCAL_COUNT(name,opt) LocalOption<size_t> cnt_##name(name, opt)
|
|
33
|
+
|
|
34
|
+
#define NESTING_GUARD(name) \
|
|
35
|
+
LocalOption<size_t> cnt_##name(name, name + 1); \
|
|
36
|
+
if (name > MAX_NESTING) throw Exception::NestingLimitError(pstate, traces); \
|
|
28
37
|
|
|
29
38
|
#define ATTACH_OPERATIONS()\
|
|
30
39
|
virtual void perform(Operation<void>* op) { (*op)(this); }\
|
|
@@ -44,7 +53,7 @@ public:\
|
|
|
44
53
|
type name(type name##__) { return name##_ = name##__; }\
|
|
45
54
|
private:
|
|
46
55
|
|
|
47
|
-
#define
|
|
56
|
+
#define HASH_PROPERTY(type, name)\
|
|
48
57
|
protected:\
|
|
49
58
|
type name##_;\
|
|
50
59
|
public:\
|
|
@@ -52,4 +61,20 @@ public:\
|
|
|
52
61
|
type name(type name##__) { hash_ = 0; return name##_ = name##__; }\
|
|
53
62
|
private:
|
|
54
63
|
|
|
64
|
+
#define ADD_CONSTREF(type, name) \
|
|
65
|
+
protected: \
|
|
66
|
+
type name##_; \
|
|
67
|
+
public: \
|
|
68
|
+
const type& name() const { return name##_; } \
|
|
69
|
+
void name(type name##__) { name##_ = name##__; } \
|
|
70
|
+
private:
|
|
71
|
+
|
|
72
|
+
#define HASH_CONSTREF(type, name) \
|
|
73
|
+
protected: \
|
|
74
|
+
type name##_; \
|
|
75
|
+
public: \
|
|
76
|
+
const type& name() const { return name##_; } \
|
|
77
|
+
void name(type name##__) { hash_ = 0; name##_ = name##__; } \
|
|
78
|
+
private:
|
|
79
|
+
|
|
55
80
|
#endif
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#include "ast.hpp"
|
|
2
|
+
|
|
3
|
+
namespace Sass {
|
|
4
|
+
|
|
5
|
+
#define IMPLEMENT_BASE_CAST(T) \
|
|
6
|
+
template<> \
|
|
7
|
+
T* Cast(AST_Node* ptr) { \
|
|
8
|
+
return dynamic_cast<T*>(ptr); \
|
|
9
|
+
}; \
|
|
10
|
+
\
|
|
11
|
+
template<> \
|
|
12
|
+
const T* Cast(const AST_Node* ptr) { \
|
|
13
|
+
return dynamic_cast<const T*>(ptr); \
|
|
14
|
+
}; \
|
|
15
|
+
|
|
16
|
+
IMPLEMENT_BASE_CAST(AST_Node)
|
|
17
|
+
IMPLEMENT_BASE_CAST(Expression)
|
|
18
|
+
IMPLEMENT_BASE_CAST(Statement)
|
|
19
|
+
IMPLEMENT_BASE_CAST(Has_Block)
|
|
20
|
+
IMPLEMENT_BASE_CAST(PreValue)
|
|
21
|
+
IMPLEMENT_BASE_CAST(Value)
|
|
22
|
+
IMPLEMENT_BASE_CAST(List)
|
|
23
|
+
IMPLEMENT_BASE_CAST(String)
|
|
24
|
+
IMPLEMENT_BASE_CAST(String_Constant)
|
|
25
|
+
IMPLEMENT_BASE_CAST(Supports_Condition)
|
|
26
|
+
IMPLEMENT_BASE_CAST(Selector)
|
|
27
|
+
IMPLEMENT_BASE_CAST(Simple_Selector)
|
|
28
|
+
|
|
29
|
+
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
#ifndef SASS_AST_FWD_DECL_H
|
|
2
2
|
#define SASS_AST_FWD_DECL_H
|
|
3
3
|
|
|
4
|
+
#include <map>
|
|
5
|
+
#include <set>
|
|
6
|
+
#include <deque>
|
|
4
7
|
#include <vector>
|
|
8
|
+
#include <typeinfo>
|
|
5
9
|
#include <iostream>
|
|
6
10
|
#include <algorithm>
|
|
7
11
|
#include <unordered_map>
|
|
8
12
|
#include <unordered_set>
|
|
9
13
|
#include "memory/SharedPtr.hpp"
|
|
14
|
+
#include "sass/functions.h"
|
|
10
15
|
|
|
11
16
|
/////////////////////////////////////////////
|
|
12
17
|
// Forward declarations for the AST visitors.
|
|
@@ -128,6 +133,9 @@ namespace Sass {
|
|
|
128
133
|
class Map;
|
|
129
134
|
typedef Map* Map_Ptr;
|
|
130
135
|
typedef Map const* Map_Ptr_Const;
|
|
136
|
+
class Function;
|
|
137
|
+
typedef Function* Function_Ptr;
|
|
138
|
+
typedef Function const* Function_Ptr_Const;
|
|
131
139
|
|
|
132
140
|
class Mixin_Call;
|
|
133
141
|
typedef Mixin_Call* Mixin_Call_Ptr;
|
|
@@ -154,9 +162,6 @@ namespace Sass {
|
|
|
154
162
|
class Variable;
|
|
155
163
|
typedef Variable* Variable_Ptr;
|
|
156
164
|
typedef Variable const* Variable_Ptr_Const;
|
|
157
|
-
class Textual;
|
|
158
|
-
typedef Textual* Textual_Ptr;
|
|
159
|
-
typedef Textual const* Textual_Ptr_Const;
|
|
160
165
|
class Number;
|
|
161
166
|
typedef Number* Number_Ptr;
|
|
162
167
|
typedef Number const* Number_Ptr_Const;
|
|
@@ -310,6 +315,7 @@ namespace Sass {
|
|
|
310
315
|
IMPL_MEM_OBJ(Expression);
|
|
311
316
|
IMPL_MEM_OBJ(List);
|
|
312
317
|
IMPL_MEM_OBJ(Map);
|
|
318
|
+
IMPL_MEM_OBJ(Function);
|
|
313
319
|
IMPL_MEM_OBJ(Binary_Expression);
|
|
314
320
|
IMPL_MEM_OBJ(Unary_Expression);
|
|
315
321
|
IMPL_MEM_OBJ(Function_Call);
|
|
@@ -317,7 +323,6 @@ namespace Sass {
|
|
|
317
323
|
IMPL_MEM_OBJ(Custom_Warning);
|
|
318
324
|
IMPL_MEM_OBJ(Custom_Error);
|
|
319
325
|
IMPL_MEM_OBJ(Variable);
|
|
320
|
-
IMPL_MEM_OBJ(Textual);
|
|
321
326
|
IMPL_MEM_OBJ(Number);
|
|
322
327
|
IMPL_MEM_OBJ(Color);
|
|
323
328
|
IMPL_MEM_OBJ(Boolean);
|
|
@@ -353,37 +358,105 @@ namespace Sass {
|
|
|
353
358
|
IMPL_MEM_OBJ(Complex_Selector);
|
|
354
359
|
IMPL_MEM_OBJ(Selector_List);
|
|
355
360
|
|
|
361
|
+
// ###########################################################################
|
|
362
|
+
// Implement compare, order and hashing operations for AST Nodes
|
|
363
|
+
// ###########################################################################
|
|
356
364
|
|
|
357
|
-
struct
|
|
358
|
-
|
|
365
|
+
struct HashNodes {
|
|
366
|
+
template <class T>
|
|
367
|
+
size_t operator() (const T& ex) const {
|
|
368
|
+
return ex.isNull() ? 0 : ex->hash();
|
|
369
|
+
}
|
|
359
370
|
};
|
|
360
|
-
struct
|
|
361
|
-
|
|
371
|
+
struct OrderNodes {
|
|
372
|
+
template <class T>
|
|
373
|
+
bool operator() (const T& lhs, const T& rhs) const {
|
|
374
|
+
return !lhs.isNull() && !rhs.isNull() && *lhs < *rhs;
|
|
375
|
+
}
|
|
362
376
|
};
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
377
|
+
struct CompareNodes {
|
|
378
|
+
template <class T>
|
|
379
|
+
bool operator() (const T& lhs, const T& rhs) const {
|
|
380
|
+
// code around sass logic issue. 1px == 1 is true
|
|
381
|
+
// but both items are still different keys in maps
|
|
382
|
+
if (dynamic_cast<Number*>(lhs.ptr()))
|
|
383
|
+
if (dynamic_cast<Number*>(rhs.ptr()))
|
|
384
|
+
return lhs->hash() == rhs->hash();
|
|
385
|
+
return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs;
|
|
386
|
+
}
|
|
366
387
|
};
|
|
367
388
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
389
|
+
// ###########################################################################
|
|
390
|
+
// some often used typedefs
|
|
391
|
+
// ###########################################################################
|
|
371
392
|
|
|
372
393
|
typedef std::unordered_map<
|
|
373
394
|
Expression_Obj, // key
|
|
374
395
|
Expression_Obj, // value
|
|
375
|
-
|
|
376
|
-
|
|
396
|
+
HashNodes, // hasher
|
|
397
|
+
CompareNodes // compare
|
|
377
398
|
> ExpressionMap;
|
|
378
399
|
typedef std::unordered_set<
|
|
379
400
|
Expression_Obj, // value
|
|
380
|
-
|
|
381
|
-
|
|
401
|
+
HashNodes, // hasher
|
|
402
|
+
CompareNodes // compare
|
|
382
403
|
> ExpressionSet;
|
|
383
404
|
|
|
384
|
-
typedef std::string
|
|
385
|
-
typedef std::vector<
|
|
386
|
-
|
|
405
|
+
typedef std::string SubSetMapKey;
|
|
406
|
+
typedef std::vector<std::string> SubSetMapKeys;
|
|
407
|
+
|
|
408
|
+
typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> SubSetMapPair;
|
|
409
|
+
typedef std::pair<Compound_Selector_Obj, Complex_Selector_Obj> SubSetMapLookup;
|
|
410
|
+
typedef std::vector<SubSetMapPair> SubSetMapPairs;
|
|
411
|
+
typedef std::vector<SubSetMapLookup> SubSetMapLookups;
|
|
412
|
+
|
|
413
|
+
typedef std::pair<Complex_Selector_Obj, SubSetMapPairs> SubSetMapResult;
|
|
414
|
+
typedef std::vector<SubSetMapResult> SubSetMapResults;
|
|
415
|
+
|
|
416
|
+
typedef std::deque<Complex_Selector_Obj> ComplexSelectorDeque;
|
|
417
|
+
typedef std::set<Simple_Selector_Obj, OrderNodes> SimpleSelectorSet;
|
|
418
|
+
typedef std::set<Complex_Selector_Obj, OrderNodes> ComplexSelectorSet;
|
|
419
|
+
typedef std::set<Compound_Selector_Obj, OrderNodes> CompoundSelectorSet;
|
|
420
|
+
typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict;
|
|
421
|
+
|
|
422
|
+
typedef std::vector<Sass_Import_Entry>* ImporterStack;
|
|
423
|
+
|
|
424
|
+
// only to switch implementations for testing
|
|
425
|
+
#define environment_map std::map
|
|
426
|
+
|
|
427
|
+
// ###########################################################################
|
|
428
|
+
// explicit type conversion functions
|
|
429
|
+
// ###########################################################################
|
|
430
|
+
|
|
431
|
+
template<class T>
|
|
432
|
+
T* Cast(AST_Node* ptr);
|
|
433
|
+
|
|
434
|
+
template<class T>
|
|
435
|
+
const T* Cast(const AST_Node* ptr);
|
|
436
|
+
|
|
437
|
+
// sometimes you know the class you want to cast to is final
|
|
438
|
+
// in this case a simple typeid check is faster and safe to use
|
|
439
|
+
|
|
440
|
+
#define DECLARE_BASE_CAST(T) \
|
|
441
|
+
template<> T* Cast(AST_Node* ptr); \
|
|
442
|
+
template<> const T* Cast(const AST_Node* ptr); \
|
|
443
|
+
|
|
444
|
+
// ###########################################################################
|
|
445
|
+
// implement specialization for final classes
|
|
446
|
+
// ###########################################################################
|
|
447
|
+
|
|
448
|
+
DECLARE_BASE_CAST(AST_Node)
|
|
449
|
+
DECLARE_BASE_CAST(Expression)
|
|
450
|
+
DECLARE_BASE_CAST(Statement)
|
|
451
|
+
DECLARE_BASE_CAST(Has_Block)
|
|
452
|
+
DECLARE_BASE_CAST(PreValue)
|
|
453
|
+
DECLARE_BASE_CAST(Value)
|
|
454
|
+
DECLARE_BASE_CAST(List)
|
|
455
|
+
DECLARE_BASE_CAST(String)
|
|
456
|
+
DECLARE_BASE_CAST(String_Constant)
|
|
457
|
+
DECLARE_BASE_CAST(Supports_Condition)
|
|
458
|
+
DECLARE_BASE_CAST(Selector)
|
|
459
|
+
DECLARE_BASE_CAST(Simple_Selector)
|
|
387
460
|
|
|
388
461
|
}
|
|
389
462
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#include "backtrace.hpp"
|
|
2
|
+
|
|
3
|
+
namespace Sass {
|
|
4
|
+
|
|
5
|
+
const std::string traces_to_string(Backtraces traces, std::string indent) {
|
|
6
|
+
|
|
7
|
+
std::stringstream ss;
|
|
8
|
+
std::string cwd(File::get_cwd());
|
|
9
|
+
|
|
10
|
+
bool first = true;
|
|
11
|
+
size_t i_beg = traces.size() - 1;
|
|
12
|
+
size_t i_end = std::string::npos;
|
|
13
|
+
for (size_t i = i_beg; i != i_end; i --) {
|
|
14
|
+
|
|
15
|
+
const Backtrace& trace = traces[i];
|
|
16
|
+
|
|
17
|
+
// make path relative to the current directory
|
|
18
|
+
std::string rel_path(File::abs2rel(trace.pstate.path, cwd, cwd));
|
|
19
|
+
|
|
20
|
+
// skip functions on error cases (unsure why ruby sass does this)
|
|
21
|
+
// if (trace.caller.substr(0, 6) == ", in f") continue;
|
|
22
|
+
|
|
23
|
+
if (first) {
|
|
24
|
+
ss << indent;
|
|
25
|
+
ss << "on line ";
|
|
26
|
+
ss << trace.pstate.line + 1;
|
|
27
|
+
ss << " of " << rel_path;
|
|
28
|
+
// ss << trace.caller;
|
|
29
|
+
first = false;
|
|
30
|
+
} else {
|
|
31
|
+
ss << trace.caller;
|
|
32
|
+
ss << std::endl;
|
|
33
|
+
ss << indent;
|
|
34
|
+
ss << "from line ";
|
|
35
|
+
ss << trace.pstate.line + 1;
|
|
36
|
+
ss << " of " << rel_path;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
ss << std::endl;
|
|
42
|
+
return ss.str();
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
};
|
|
@@ -1,75 +1,28 @@
|
|
|
1
1
|
#ifndef SASS_BACKTRACE_H
|
|
2
2
|
#define SASS_BACKTRACE_H
|
|
3
3
|
|
|
4
|
+
#include <vector>
|
|
4
5
|
#include <sstream>
|
|
5
|
-
|
|
6
6
|
#include "file.hpp"
|
|
7
7
|
#include "position.hpp"
|
|
8
8
|
|
|
9
9
|
namespace Sass {
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
struct Backtrace {
|
|
13
12
|
|
|
14
|
-
Backtrace* parent;
|
|
15
13
|
ParserState pstate;
|
|
16
|
-
std::string
|
|
14
|
+
std::string caller;
|
|
17
15
|
|
|
18
|
-
Backtrace(
|
|
19
|
-
:
|
|
20
|
-
pstate(pstate),
|
|
16
|
+
Backtrace(ParserState pstate, std::string c = "")
|
|
17
|
+
: pstate(pstate),
|
|
21
18
|
caller(c)
|
|
22
19
|
{ }
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
{
|
|
26
|
-
size_t i = -1;
|
|
27
|
-
std::stringstream ss;
|
|
28
|
-
std::string cwd(Sass::File::get_cwd());
|
|
29
|
-
Backtrace* this_point = this;
|
|
30
|
-
|
|
31
|
-
if (!warning) ss << std::endl << "Backtrace:";
|
|
32
|
-
// the first tracepoint (which is parent-less) is an empty placeholder
|
|
33
|
-
while (this_point->parent) {
|
|
34
|
-
|
|
35
|
-
// make path relative to the current directory
|
|
36
|
-
std::string rel_path(Sass::File::abs2rel(this_point->pstate.path, cwd, cwd));
|
|
37
|
-
|
|
38
|
-
if (warning) {
|
|
39
|
-
ss << std::endl
|
|
40
|
-
<< "\t"
|
|
41
|
-
<< (++i == 0 ? "on" : "from")
|
|
42
|
-
<< " line "
|
|
43
|
-
<< this_point->pstate.line + 1
|
|
44
|
-
<< " of "
|
|
45
|
-
<< rel_path;
|
|
46
|
-
} else {
|
|
47
|
-
ss << std::endl
|
|
48
|
-
<< "\t"
|
|
49
|
-
<< rel_path
|
|
50
|
-
<< ":"
|
|
51
|
-
<< this_point->pstate.line + 1
|
|
52
|
-
<< this_point->parent->caller;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
this_point = this_point->parent;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return ss.str();
|
|
59
|
-
}
|
|
21
|
+
};
|
|
60
22
|
|
|
61
|
-
|
|
62
|
-
{
|
|
63
|
-
size_t d = 0;
|
|
64
|
-
Backtrace* p = parent;
|
|
65
|
-
while (p) {
|
|
66
|
-
++d;
|
|
67
|
-
p = p->parent;
|
|
68
|
-
}
|
|
69
|
-
return d-1;
|
|
70
|
-
}
|
|
23
|
+
typedef std::vector<Backtrace> Backtraces;
|
|
71
24
|
|
|
72
|
-
|
|
25
|
+
const std::string traces_to_string(Backtraces traces, std::string indent = "\t");
|
|
73
26
|
|
|
74
27
|
}
|
|
75
28
|
|
data/ext/libsass/src/bind.cpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "bind.hpp"
|
|
3
3
|
#include "ast.hpp"
|
|
4
4
|
#include "context.hpp"
|
|
5
|
+
#include "expand.hpp"
|
|
5
6
|
#include "eval.hpp"
|
|
6
7
|
#include <map>
|
|
7
8
|
#include <iostream>
|
|
@@ -14,9 +15,11 @@ namespace Sass {
|
|
|
14
15
|
std::string callee(type + " " + name);
|
|
15
16
|
|
|
16
17
|
std::map<std::string, Parameter_Obj> param_map;
|
|
18
|
+
List_Obj varargs = SASS_MEMORY_NEW(List, as->pstate());
|
|
19
|
+
varargs->is_arglist(true); // enable keyword size handling
|
|
17
20
|
|
|
18
21
|
for (size_t i = 0, L = as->length(); i < L; ++i) {
|
|
19
|
-
if (auto str =
|
|
22
|
+
if (auto str = Cast<String_Quoted>((*as)[i]->value())) {
|
|
20
23
|
// force optional quotes (only if needed)
|
|
21
24
|
if (str->quote_mark()) {
|
|
22
25
|
str->quote_mark('*');
|
|
@@ -42,7 +45,7 @@ namespace Sass {
|
|
|
42
45
|
if (ip >= LP) {
|
|
43
46
|
// skip empty rest arguments
|
|
44
47
|
if (a->is_rest_argument()) {
|
|
45
|
-
if (List_Obj l =
|
|
48
|
+
if (List_Obj l = Cast<List>(a->value())) {
|
|
46
49
|
if (l->length() == 0) {
|
|
47
50
|
++ ia; continue;
|
|
48
51
|
}
|
|
@@ -51,7 +54,7 @@ namespace Sass {
|
|
|
51
54
|
std::stringstream msg;
|
|
52
55
|
msg << "wrong number of arguments (" << LA << " for " << LP << ")";
|
|
53
56
|
msg << " for `" << name << "'";
|
|
54
|
-
return error(msg.str(), as->pstate());
|
|
57
|
+
return error(msg.str(), as->pstate(), eval->exp.traces);
|
|
55
58
|
}
|
|
56
59
|
Parameter_Obj p = ps->at(ip);
|
|
57
60
|
|
|
@@ -61,7 +64,7 @@ namespace Sass {
|
|
|
61
64
|
if (a->is_rest_argument()) {
|
|
62
65
|
|
|
63
66
|
// We should always get a list for rest arguments
|
|
64
|
-
if (List_Obj rest =
|
|
67
|
+
if (List_Obj rest = Cast<List>(a->value())) {
|
|
65
68
|
// create a new list object for wrapped items
|
|
66
69
|
List_Ptr arglist = SASS_MEMORY_NEW(List,
|
|
67
70
|
p->pstate(),
|
|
@@ -70,12 +73,12 @@ namespace Sass {
|
|
|
70
73
|
true);
|
|
71
74
|
// wrap each item from list as an argument
|
|
72
75
|
for (Expression_Obj item : rest->elements()) {
|
|
73
|
-
if (Argument_Obj arg =
|
|
76
|
+
if (Argument_Obj arg = Cast<Argument>(item)) {
|
|
74
77
|
arglist->append(SASS_MEMORY_COPY(arg)); // copy
|
|
75
78
|
} else {
|
|
76
79
|
arglist->append(SASS_MEMORY_NEW(Argument,
|
|
77
80
|
item->pstate(),
|
|
78
|
-
|
|
81
|
+
item,
|
|
79
82
|
"",
|
|
80
83
|
false,
|
|
81
84
|
false));
|
|
@@ -93,15 +96,20 @@ namespace Sass {
|
|
|
93
96
|
// expand keyword arguments into their parameters
|
|
94
97
|
List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true);
|
|
95
98
|
env->local_frame()[p->name()] = arglist;
|
|
96
|
-
Map_Obj argmap =
|
|
99
|
+
Map_Obj argmap = Cast<Map>(a->value());
|
|
97
100
|
for (auto key : argmap->keys()) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
if (String_Constant_Obj str = Cast<String_Constant>(key)) {
|
|
102
|
+
std::string param = unquote(str->value());
|
|
103
|
+
arglist->append(SASS_MEMORY_NEW(Argument,
|
|
104
|
+
key->pstate(),
|
|
105
|
+
argmap->at(key),
|
|
106
|
+
"$" + param,
|
|
107
|
+
false,
|
|
108
|
+
false));
|
|
109
|
+
} else {
|
|
110
|
+
eval->exp.traces.push_back(Backtrace(key->pstate()));
|
|
111
|
+
throw Exception::InvalidVarKwdType(key->pstate(), eval->exp.traces, key->inspect(), a);
|
|
112
|
+
}
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
} else {
|
|
@@ -117,25 +125,25 @@ namespace Sass {
|
|
|
117
125
|
// get and post inc
|
|
118
126
|
a = (*as)[ia++];
|
|
119
127
|
// maybe we have another list as argument
|
|
120
|
-
List_Obj ls =
|
|
128
|
+
List_Obj ls = Cast<List>(a->value());
|
|
121
129
|
// skip any list completely if empty
|
|
122
130
|
if (ls && ls->empty() && a->is_rest_argument()) continue;
|
|
123
131
|
|
|
124
132
|
Expression_Obj value = a->value();
|
|
125
|
-
if (Argument_Obj arg =
|
|
126
|
-
arglist->append(
|
|
133
|
+
if (Argument_Obj arg = Cast<Argument>(value)) {
|
|
134
|
+
arglist->append(arg);
|
|
127
135
|
}
|
|
128
136
|
// check if we have rest argument
|
|
129
137
|
else if (a->is_rest_argument()) {
|
|
130
138
|
// preserve the list separator from rest args
|
|
131
|
-
if (List_Obj rest =
|
|
139
|
+
if (List_Obj rest = Cast<List>(a->value())) {
|
|
132
140
|
arglist->separator(rest->separator());
|
|
133
141
|
|
|
134
|
-
for (size_t i = 0, L = rest->
|
|
135
|
-
Expression_Obj obj = rest->
|
|
142
|
+
for (size_t i = 0, L = rest->length(); i < L; ++i) {
|
|
143
|
+
Expression_Obj obj = rest->value_at_index(i);
|
|
136
144
|
arglist->append(SASS_MEMORY_NEW(Argument,
|
|
137
145
|
obj->pstate(),
|
|
138
|
-
|
|
146
|
+
obj,
|
|
139
147
|
"",
|
|
140
148
|
false,
|
|
141
149
|
false));
|
|
@@ -155,7 +163,7 @@ namespace Sass {
|
|
|
155
163
|
}
|
|
156
164
|
}
|
|
157
165
|
// assign new arglist to environment
|
|
158
|
-
env->local_frame()[p->name()] =
|
|
166
|
+
env->local_frame()[p->name()] = arglist;
|
|
159
167
|
}
|
|
160
168
|
// consumed parameter
|
|
161
169
|
++ip;
|
|
@@ -166,9 +174,16 @@ namespace Sass {
|
|
|
166
174
|
// If the current argument is the rest argument, extract a value for processing
|
|
167
175
|
else if (a->is_rest_argument()) {
|
|
168
176
|
// normal param and rest arg
|
|
169
|
-
List_Obj arglist =
|
|
177
|
+
List_Obj arglist = Cast<List>(a->value());
|
|
178
|
+
if (!arglist) {
|
|
179
|
+
if (Expression_Obj arg = Cast<Expression>(a->value())) {
|
|
180
|
+
arglist = SASS_MEMORY_NEW(List, a->pstate(), 1);
|
|
181
|
+
arglist->append(arg);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
170
185
|
// empty rest arg - treat all args as default values
|
|
171
|
-
if (!arglist->length()) {
|
|
186
|
+
if (!arglist || !arglist->length()) {
|
|
172
187
|
break;
|
|
173
188
|
} else {
|
|
174
189
|
if (arglist->length() > LP - ip && !ps->has_rest_parameter()) {
|
|
@@ -187,8 +202,8 @@ namespace Sass {
|
|
|
187
202
|
}
|
|
188
203
|
// otherwise move one of the rest args into the param, converting to argument if necessary
|
|
189
204
|
Expression_Obj obj = arglist->at(0);
|
|
190
|
-
if (!(a =
|
|
191
|
-
Expression_Ptr a_to_convert =
|
|
205
|
+
if (!(a = Cast<Argument>(obj))) {
|
|
206
|
+
Expression_Ptr a_to_convert = obj;
|
|
192
207
|
a = SASS_MEMORY_NEW(Argument,
|
|
193
208
|
a_to_convert->pstate(),
|
|
194
209
|
a_to_convert,
|
|
@@ -202,17 +217,22 @@ namespace Sass {
|
|
|
202
217
|
}
|
|
203
218
|
|
|
204
219
|
} else if (a->is_keyword_argument()) {
|
|
205
|
-
Map_Obj argmap =
|
|
220
|
+
Map_Obj argmap = Cast<Map>(a->value());
|
|
206
221
|
|
|
207
222
|
for (auto key : argmap->keys()) {
|
|
208
|
-
|
|
223
|
+
String_Constant_Ptr val = Cast<String_Constant>(key);
|
|
224
|
+
if (val == NULL) {
|
|
225
|
+
eval->exp.traces.push_back(Backtrace(key->pstate()));
|
|
226
|
+
throw Exception::InvalidVarKwdType(key->pstate(), eval->exp.traces, key->inspect(), a);
|
|
227
|
+
}
|
|
228
|
+
std::string param = "$" + unquote(val->value());
|
|
209
229
|
|
|
210
|
-
if (!param_map.count(
|
|
230
|
+
if (!param_map.count(param)) {
|
|
211
231
|
std::stringstream msg;
|
|
212
|
-
msg << callee << " has no parameter named " <<
|
|
213
|
-
error(msg.str(), a->pstate());
|
|
232
|
+
msg << callee << " has no parameter named " << param;
|
|
233
|
+
error(msg.str(), a->pstate(), eval->exp.traces);
|
|
214
234
|
}
|
|
215
|
-
env->local_frame()[
|
|
235
|
+
env->local_frame()[param] = argmap->at(key);
|
|
216
236
|
}
|
|
217
237
|
++ia;
|
|
218
238
|
continue;
|
|
@@ -225,32 +245,38 @@ namespace Sass {
|
|
|
225
245
|
std::stringstream msg;
|
|
226
246
|
msg << "parameter " << p->name()
|
|
227
247
|
<< " provided more than once in call to " << callee;
|
|
228
|
-
error(msg.str(), a->pstate());
|
|
248
|
+
error(msg.str(), a->pstate(), eval->exp.traces);
|
|
229
249
|
}
|
|
230
250
|
// ordinal arg -- bind it to the next param
|
|
231
|
-
env->local_frame()[p->name()] =
|
|
251
|
+
env->local_frame()[p->name()] = a->value();
|
|
232
252
|
++ip;
|
|
233
253
|
}
|
|
234
254
|
else {
|
|
235
255
|
// named arg -- bind it to the appropriately named param
|
|
236
256
|
if (!param_map.count(a->name())) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
257
|
+
if (ps->has_rest_parameter()) {
|
|
258
|
+
varargs->append(a);
|
|
259
|
+
} else {
|
|
260
|
+
std::stringstream msg;
|
|
261
|
+
msg << callee << " has no parameter named " << a->name();
|
|
262
|
+
error(msg.str(), a->pstate(), eval->exp.traces);
|
|
263
|
+
}
|
|
240
264
|
}
|
|
241
|
-
if (param_map[a->name()]
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
265
|
+
if (param_map[a->name()]) {
|
|
266
|
+
if (param_map[a->name()]->is_rest_parameter()) {
|
|
267
|
+
std::stringstream msg;
|
|
268
|
+
msg << "argument " << a->name() << " of " << callee
|
|
269
|
+
<< "cannot be used as named argument";
|
|
270
|
+
error(msg.str(), a->pstate(), eval->exp.traces);
|
|
271
|
+
}
|
|
246
272
|
}
|
|
247
273
|
if (env->has_local(a->name())) {
|
|
248
274
|
std::stringstream msg;
|
|
249
275
|
msg << "parameter " << p->name()
|
|
250
276
|
<< "provided more than once in call to " << callee;
|
|
251
|
-
error(msg.str(), a->pstate());
|
|
277
|
+
error(msg.str(), a->pstate(), eval->exp.traces);
|
|
252
278
|
}
|
|
253
|
-
env->local_frame()[a->name()] =
|
|
279
|
+
env->local_frame()[a->name()] = a->value();
|
|
254
280
|
}
|
|
255
281
|
}
|
|
256
282
|
// EO while ia
|
|
@@ -265,11 +291,7 @@ namespace Sass {
|
|
|
265
291
|
// cerr << "********" << endl;
|
|
266
292
|
if (!env->has_local(leftover->name())) {
|
|
267
293
|
if (leftover->is_rest_parameter()) {
|
|
268
|
-
env->local_frame()[leftover->name()] =
|
|
269
|
-
leftover->pstate(),
|
|
270
|
-
0,
|
|
271
|
-
SASS_COMMA,
|
|
272
|
-
true);
|
|
294
|
+
env->local_frame()[leftover->name()] = varargs;
|
|
273
295
|
}
|
|
274
296
|
else if (leftover->default_value()) {
|
|
275
297
|
Expression_Ptr dv = leftover->default_value()->perform(eval);
|
|
@@ -277,7 +299,7 @@ namespace Sass {
|
|
|
277
299
|
}
|
|
278
300
|
else {
|
|
279
301
|
// param is unbound and has no default value -- error
|
|
280
|
-
throw Exception::MissingArgument(as->pstate(), name, leftover->name(), type);
|
|
302
|
+
throw Exception::MissingArgument(as->pstate(), eval->exp.traces, name, leftover->name(), type);
|
|
281
303
|
}
|
|
282
304
|
}
|
|
283
305
|
}
|