sassc 1.10.1 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/ext/libsass/.github/CONTRIBUTING.md +65 -0
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
- data/ext/libsass/Makefile +8 -3
- data/ext/libsass/Makefile.conf +28 -22
- data/ext/libsass/Readme.md +14 -7
- data/ext/libsass/configure.ac +5 -8
- data/ext/libsass/docs/api-context-internal.md +3 -0
- data/ext/libsass/docs/api-context.md +7 -0
- data/ext/libsass/docs/api-doc.md +4 -0
- data/ext/libsass/docs/api-importer.md +2 -0
- data/ext/libsass/docs/api-value-example.md +55 -0
- data/ext/libsass/docs/api-value.md +49 -22
- data/ext/libsass/docs/implementations.md +4 -0
- data/ext/libsass/include/sass/base.h +5 -4
- data/ext/libsass/include/sass/context.h +3 -0
- data/ext/libsass/include/sass/values.h +28 -27
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/script/ci-build-libsass +3 -3
- data/ext/libsass/script/ci-install-deps +12 -3
- data/ext/libsass/src/ast.cpp +321 -212
- data/ext/libsass/src/ast.hpp +273 -165
- data/ext/libsass/src/ast_factory.hpp +4 -5
- data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
- data/ext/libsass/src/bind.cpp +2 -7
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/check_nesting.cpp +379 -0
- data/ext/libsass/src/check_nesting.hpp +60 -0
- data/ext/libsass/src/constants.cpp +7 -6
- data/ext/libsass/src/constants.hpp +2 -1
- data/ext/libsass/src/context.cpp +7 -1
- data/ext/libsass/src/context.hpp +1 -1
- data/ext/libsass/src/cssize.cpp +76 -32
- data/ext/libsass/src/cssize.hpp +7 -8
- data/ext/libsass/src/debugger.hpp +70 -40
- data/ext/libsass/src/error_handling.cpp +15 -2
- data/ext/libsass/src/error_handling.hpp +19 -0
- data/ext/libsass/src/eval.cpp +107 -161
- data/ext/libsass/src/eval.hpp +12 -8
- data/ext/libsass/src/expand.cpp +81 -74
- data/ext/libsass/src/expand.hpp +13 -12
- data/ext/libsass/src/extend.cpp +149 -142
- data/ext/libsass/src/extend.hpp +10 -3
- data/ext/libsass/src/file.cpp +2 -1
- data/ext/libsass/src/functions.cpp +96 -59
- data/ext/libsass/src/functions.hpp +2 -2
- data/ext/libsass/src/inspect.cpp +33 -45
- data/ext/libsass/src/inspect.hpp +7 -7
- data/ext/libsass/src/json.cpp +17 -5
- data/ext/libsass/src/lexer.cpp +3 -3
- data/ext/libsass/src/listize.cpp +10 -10
- data/ext/libsass/src/listize.hpp +3 -3
- data/ext/libsass/src/node.cpp +30 -30
- data/ext/libsass/src/node.hpp +13 -13
- data/ext/libsass/src/operation.hpp +21 -19
- data/ext/libsass/src/output.cpp +48 -103
- data/ext/libsass/src/output.hpp +0 -1
- data/ext/libsass/src/parser.cpp +161 -133
- data/ext/libsass/src/parser.hpp +10 -7
- data/ext/libsass/src/remove_placeholders.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.hpp +1 -1
- data/ext/libsass/src/sass.cpp +21 -0
- data/ext/libsass/src/sass.hpp +8 -1
- data/ext/libsass/src/sass2scss.cpp +14 -3
- data/ext/libsass/src/sass_context.cpp +69 -24
- data/ext/libsass/src/sass_context.hpp +3 -0
- data/ext/libsass/src/source_map.cpp +22 -10
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.hpp +3 -1
- data/ext/libsass/src/util.cpp +20 -16
- data/ext/libsass/src/util.hpp +2 -1
- data/ext/libsass/win/libsass.targets +2 -0
- data/ext/libsass/win/libsass.vcxproj.filters +6 -0
- data/lib/sassc/engine.rb +5 -0
- data/lib/sassc/native/native_functions_api.rb +13 -1
- data/lib/sassc/script/value_conversion.rb +11 -1
- data/lib/sassc/script/value_conversion/list.rb +23 -0
- data/lib/sassc/version.rb +1 -1
- data/test/engine_test.rb +18 -2
- data/test/functions_test.rb +30 -0
- data/test/native_test.rb +1 -1
- metadata +8 -3
@@ -35,11 +35,19 @@ namespace Sass {
|
|
35
35
|
: Base(pstate), fn(fn), arg(arg), type(type), value(value)
|
36
36
|
{
|
37
37
|
msg = arg + ": \"";
|
38
|
-
msg += value->to_string(Sass_Inspect_Options());
|
38
|
+
if (value) msg += value->to_string(Sass_Inspect_Options());
|
39
39
|
msg += "\" is not a " + type;
|
40
40
|
msg += " for `" + fn + "'";
|
41
41
|
}
|
42
42
|
|
43
|
+
MissingArgument::MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype)
|
44
|
+
: Base(pstate), fn(fn), arg(arg), fntype(fntype)
|
45
|
+
{
|
46
|
+
msg = fntype + " " + fn;
|
47
|
+
msg += " is missing argument ";
|
48
|
+
msg += arg + ".";
|
49
|
+
}
|
50
|
+
|
43
51
|
InvalidSyntax::InvalidSyntax(ParserState pstate, std::string msg, std::vector<Sass_Import_Entry>* import_stack)
|
44
52
|
: Base(pstate, msg, import_stack)
|
45
53
|
{ }
|
@@ -74,7 +82,6 @@ namespace Sass {
|
|
74
82
|
: Base(org.pstate()), dup(dup), org(org)
|
75
83
|
{
|
76
84
|
msg = "Duplicate key ";
|
77
|
-
dup.get_duplicate_key()->is_delayed(false);
|
78
85
|
msg += dup.get_duplicate_key()->inspect();
|
79
86
|
msg += " in map (";
|
80
87
|
msg += org.inspect();
|
@@ -97,6 +104,12 @@ namespace Sass {
|
|
97
104
|
msg += " isn't a valid CSS value.";
|
98
105
|
}
|
99
106
|
|
107
|
+
StackError::StackError(const AST_Node& node)
|
108
|
+
: Base(node.pstate()), node(node)
|
109
|
+
{
|
110
|
+
msg = "stack level too deep";
|
111
|
+
}
|
112
|
+
|
100
113
|
IncompatibleUnits::IncompatibleUnits(const Number& lhs, const Number& rhs)
|
101
114
|
: lhs(lhs), rhs(rhs)
|
102
115
|
{
|
@@ -45,6 +45,16 @@ namespace Sass {
|
|
45
45
|
virtual ~InvalidParent() throw() {};
|
46
46
|
};
|
47
47
|
|
48
|
+
class MissingArgument : public Base {
|
49
|
+
protected:
|
50
|
+
std::string fn;
|
51
|
+
std::string arg;
|
52
|
+
std::string fntype;
|
53
|
+
public:
|
54
|
+
MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype);
|
55
|
+
virtual ~MissingArgument() throw() {};
|
56
|
+
};
|
57
|
+
|
48
58
|
class InvalidArgumentType : public Base {
|
49
59
|
protected:
|
50
60
|
std::string fn;
|
@@ -115,6 +125,15 @@ namespace Sass {
|
|
115
125
|
virtual ~InvalidValue() throw() {};
|
116
126
|
};
|
117
127
|
|
128
|
+
class StackError : public Base {
|
129
|
+
protected:
|
130
|
+
const AST_Node& node;
|
131
|
+
public:
|
132
|
+
StackError(const AST_Node& node);
|
133
|
+
virtual const char* errtype() const { return "SystemStackError"; }
|
134
|
+
virtual ~StackError() throw() {};
|
135
|
+
};
|
136
|
+
|
118
137
|
class IncompatibleUnits : public OperationError {
|
119
138
|
protected:
|
120
139
|
const Number& lhs;
|
data/ext/libsass/src/eval.cpp
CHANGED
@@ -31,7 +31,14 @@ namespace Sass {
|
|
31
31
|
inline double sub(double x, double y) { return x - y; }
|
32
32
|
inline double mul(double x, double y) { return x * y; }
|
33
33
|
inline double div(double x, double y) { return x / y; } // x/0 checked by caller
|
34
|
-
inline double mod(double x, double y) {
|
34
|
+
inline double mod(double x, double y) { // x/0 checked by caller
|
35
|
+
if ((x > 0 && y < 0) || (x < 0 && y > 0)) {
|
36
|
+
double ret = std::fmod(x, y);
|
37
|
+
return ret ? ret + y : ret;
|
38
|
+
} else {
|
39
|
+
return std::fmod(x, y);
|
40
|
+
}
|
41
|
+
}
|
35
42
|
typedef double (*bop)(double, double);
|
36
43
|
bop ops[Sass_OP::NUM_OPS] = {
|
37
44
|
0, 0, // and, or
|
@@ -41,7 +48,9 @@ namespace Sass {
|
|
41
48
|
|
42
49
|
Eval::Eval(Expand& exp)
|
43
50
|
: exp(exp),
|
44
|
-
ctx(exp.ctx)
|
51
|
+
ctx(exp.ctx),
|
52
|
+
force(false),
|
53
|
+
is_in_comment(false)
|
45
54
|
{ }
|
46
55
|
Eval::~Eval() { }
|
47
56
|
|
@@ -55,7 +64,7 @@ namespace Sass {
|
|
55
64
|
return exp.environment();
|
56
65
|
}
|
57
66
|
|
58
|
-
|
67
|
+
CommaSequence_Selector* Eval::selector()
|
59
68
|
{
|
60
69
|
return exp.selector();
|
61
70
|
}
|
@@ -221,7 +230,7 @@ namespace Sass {
|
|
221
230
|
if (expr->concrete_type() == Expression::MAP) {
|
222
231
|
map = static_cast<Map*>(expr);
|
223
232
|
}
|
224
|
-
else if (
|
233
|
+
else if (CommaSequence_Selector* ls = dynamic_cast<CommaSequence_Selector*>(expr)) {
|
225
234
|
Listize listize(ctx.mem);
|
226
235
|
list = dynamic_cast<List*>(ls->perform(&listize));
|
227
236
|
}
|
@@ -255,7 +264,7 @@ namespace Sass {
|
|
255
264
|
}
|
256
265
|
}
|
257
266
|
else {
|
258
|
-
if (list->length() == 1 && dynamic_cast<
|
267
|
+
if (list->length() == 1 && dynamic_cast<CommaSequence_Selector*>(list)) {
|
259
268
|
list = dynamic_cast<Vectorized<Expression*>*>(list);
|
260
269
|
}
|
261
270
|
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
@@ -436,7 +445,7 @@ namespace Sass {
|
|
436
445
|
Expression* key = (*l)[i+0]->perform(this);
|
437
446
|
Expression* val = (*l)[i+1]->perform(this);
|
438
447
|
// make sure the color key never displays its real name
|
439
|
-
key->is_delayed(true);
|
448
|
+
key->is_delayed(true); // verified
|
440
449
|
*lm << std::make_pair(key, val);
|
441
450
|
}
|
442
451
|
if (lm->has_duplicate_key()) {
|
@@ -497,21 +506,13 @@ namespace Sass {
|
|
497
506
|
String_Schema* ret_schema = 0;
|
498
507
|
enum Sass_OP op_type = b->type();
|
499
508
|
|
500
|
-
// don't eval delayed expressions (the '/' when used as a separator)
|
501
|
-
if (op_type == Sass_OP::DIV && b->is_delayed()) {
|
502
|
-
b->right(b->right()->perform(this));
|
503
|
-
b->left(b->left()->perform(this));
|
504
|
-
return b;
|
505
|
-
}
|
506
|
-
|
507
509
|
// only the last item will be used to eval the binary expression
|
508
510
|
if (String_Schema* s_l = dynamic_cast<String_Schema*>(b->left())) {
|
509
511
|
if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
|
510
|
-
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema,
|
512
|
+
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, b->pstate());
|
511
513
|
Binary_Expression* bin_ex = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, b->pstate(),
|
512
514
|
b->op(), s_l->last(), b->right());
|
513
|
-
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed());
|
514
|
-
// bin_ex->is_interpolant(b->left()->is_interpolant());
|
515
|
+
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
|
515
516
|
for (size_t i = 0; i < s_l->length() - 1; ++i) {
|
516
517
|
*ret_schema << s_l->at(i)->perform(this);
|
517
518
|
}
|
@@ -521,11 +522,10 @@ namespace Sass {
|
|
521
522
|
}
|
522
523
|
if (String_Schema* s_r = dynamic_cast<String_Schema*>(b->right())) {
|
523
524
|
if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
|
524
|
-
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema,
|
525
|
+
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, b->pstate());
|
525
526
|
Binary_Expression* bin_ex = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, b->pstate(),
|
526
527
|
b->op(), b->left(), s_r->first());
|
527
|
-
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed());
|
528
|
-
// if (op_type == Sass_OP::SUB && b->is_right_interpolant()) bin_ex->is_interpolant(true);
|
528
|
+
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
|
529
529
|
*ret_schema << bin_ex->perform(this);
|
530
530
|
for (size_t i = 1; i < s_r->length(); ++i) {
|
531
531
|
*ret_schema << s_r->at(i)->perform(this);
|
@@ -535,34 +535,18 @@ namespace Sass {
|
|
535
535
|
}
|
536
536
|
|
537
537
|
|
538
|
+
b = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, *b);
|
538
539
|
// don't eval delayed expressions (the '/' when used as a separator)
|
539
|
-
if (op_type == Sass_OP::DIV && b->is_delayed()) {
|
540
|
+
if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
|
540
541
|
b->right(b->right()->perform(this));
|
541
542
|
b->left(b->left()->perform(this));
|
542
543
|
return b;
|
543
544
|
}
|
544
545
|
|
545
|
-
// b->is_delayed(false);
|
546
546
|
Expression* lhs = b->left();
|
547
547
|
Expression* rhs = b->right();
|
548
548
|
|
549
|
-
//
|
550
|
-
// bool delay_rhs = false;
|
551
|
-
|
552
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(lhs)) {
|
553
|
-
if (schema->is_right_interpolant()) {
|
554
|
-
b->is_delayed(true);
|
555
|
-
// delay_lhs = true;
|
556
|
-
}
|
557
|
-
}
|
558
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(rhs)) {
|
559
|
-
if (schema->is_left_interpolant()) {
|
560
|
-
b->is_delayed(true);
|
561
|
-
// delay_rhs = true;
|
562
|
-
}
|
563
|
-
}
|
564
|
-
|
565
|
-
// maybe fully evaluate structure
|
549
|
+
// fully evaluate their values
|
566
550
|
if (op_type == Sass_OP::EQ ||
|
567
551
|
op_type == Sass_OP::NEQ ||
|
568
552
|
op_type == Sass_OP::GT ||
|
@@ -570,43 +554,16 @@ namespace Sass {
|
|
570
554
|
op_type == Sass_OP::LT ||
|
571
555
|
op_type == Sass_OP::LTE)
|
572
556
|
{
|
573
|
-
|
574
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(lhs)) {
|
575
|
-
if (schema->has_interpolants()) {
|
576
|
-
b->is_delayed(true);
|
577
|
-
}
|
578
|
-
}
|
579
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(rhs)) {
|
580
|
-
if (schema->has_interpolants()) {
|
581
|
-
b->is_delayed(true);
|
582
|
-
}
|
583
|
-
}
|
584
|
-
lhs->is_expanded(false);
|
585
|
-
lhs->set_delayed(false);
|
586
|
-
lhs = lhs->perform(this);
|
557
|
+
LOCAL_FLAG(force, true);
|
587
558
|
lhs->is_expanded(false);
|
588
559
|
lhs->set_delayed(false);
|
589
560
|
lhs = lhs->perform(this);
|
590
561
|
rhs->is_expanded(false);
|
591
562
|
rhs->set_delayed(false);
|
592
563
|
rhs = rhs->perform(this);
|
593
|
-
rhs->is_expanded(false);
|
594
|
-
rhs->set_delayed(false);
|
595
|
-
rhs = rhs->perform(this);
|
596
|
-
}
|
597
|
-
else
|
598
|
-
{
|
599
|
-
// rhs->set_delayed(false);
|
600
|
-
// rhs = rhs->perform(this);
|
601
564
|
}
|
602
|
-
|
603
|
-
|
604
|
-
lhs = lhs->perform(this);
|
605
|
-
lhs->is_delayed(false);
|
606
|
-
while (typeid(*lhs) == typeid(Binary_Expression)) {
|
607
|
-
Binary_Expression* lhs_ex = static_cast<Binary_Expression*>(lhs);
|
608
|
-
if (lhs_ex->type() == Sass_OP::DIV && lhs_ex->is_delayed()) break;
|
609
|
-
lhs = Eval::operator()(lhs_ex);
|
565
|
+
else {
|
566
|
+
lhs = lhs->perform(this);
|
610
567
|
}
|
611
568
|
|
612
569
|
switch (op_type) {
|
@@ -624,19 +581,6 @@ namespace Sass {
|
|
624
581
|
// not a logical connective, so go ahead and eval the rhs
|
625
582
|
rhs = rhs->perform(this);
|
626
583
|
|
627
|
-
// upgrade string to number if possible (issue #948)
|
628
|
-
if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL) {
|
629
|
-
if (String_Constant* str = dynamic_cast<String_Constant*>(rhs)) {
|
630
|
-
std::string value(str->value());
|
631
|
-
const char* start = value.c_str();
|
632
|
-
if (Prelexer::sequence < Prelexer::number >(start) != 0) {
|
633
|
-
rhs = SASS_MEMORY_NEW(ctx.mem, Textual, rhs->pstate(), Textual::DIMENSION, str->value());
|
634
|
-
rhs->is_delayed(false); rhs = rhs->perform(this);
|
635
|
-
}
|
636
|
-
}
|
637
|
-
}
|
638
|
-
|
639
|
-
|
640
584
|
Expression::Concrete_Type l_type = lhs->concrete_type();
|
641
585
|
Expression::Concrete_Type r_type = rhs->concrete_type();
|
642
586
|
|
@@ -662,16 +606,16 @@ namespace Sass {
|
|
662
606
|
std::string value(str->value());
|
663
607
|
const char* start = value.c_str();
|
664
608
|
if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
|
665
|
-
lhs = SASS_MEMORY_NEW(ctx.mem, Textual,
|
666
|
-
lhs
|
609
|
+
lhs = SASS_MEMORY_NEW(ctx.mem, Textual, b->pstate(), Textual::DIMENSION, str->value());
|
610
|
+
lhs = lhs->perform(this);
|
667
611
|
}
|
668
612
|
}
|
669
613
|
if (String_Constant* str = dynamic_cast<String_Constant*>(rhs)) {
|
670
614
|
std::string value(str->value());
|
671
615
|
const char* start = value.c_str();
|
672
616
|
if (Prelexer::sequence < Prelexer::number >(start) != 0) {
|
673
|
-
rhs = SASS_MEMORY_NEW(ctx.mem, Textual,
|
674
|
-
rhs
|
617
|
+
rhs = SASS_MEMORY_NEW(ctx.mem, Textual, b->pstate(), Textual::DIMENSION, str->value());
|
618
|
+
rhs = rhs->perform(this);
|
675
619
|
}
|
676
620
|
}
|
677
621
|
}
|
@@ -699,7 +643,7 @@ namespace Sass {
|
|
699
643
|
str += b->separator();
|
700
644
|
if (b->op().ws_after) str += " ";
|
701
645
|
str += v_r->to_string(ctx.c_options);
|
702
|
-
String_Constant* val = SASS_MEMORY_NEW(ctx.mem, String_Constant,
|
646
|
+
String_Constant* val = SASS_MEMORY_NEW(ctx.mem, String_Constant, b->pstate(), str);
|
703
647
|
val->is_interpolant(b->left()->has_interpolant());
|
704
648
|
return val;
|
705
649
|
}
|
@@ -760,6 +704,13 @@ namespace Sass {
|
|
760
704
|
b->is_interpolant();
|
761
705
|
if (op_type == Sass_OP::SUB) interpolant = false;
|
762
706
|
// if (op_type == Sass_OP::DIV) interpolant = true;
|
707
|
+
// check for type violations
|
708
|
+
if (l_type == Expression::MAP) {
|
709
|
+
throw Exception::InvalidValue(*v_l);
|
710
|
+
}
|
711
|
+
if (r_type == Expression::MAP) {
|
712
|
+
throw Exception::InvalidValue(*v_r);
|
713
|
+
}
|
763
714
|
Value* ex = op_strings(ctx.mem, b->op(), *v_l, *v_r, ctx.c_options, &pstate, !interpolant); // pass true to compress
|
764
715
|
if (String_Constant* str = dynamic_cast<String_Constant*>(ex))
|
765
716
|
{
|
@@ -815,7 +766,20 @@ namespace Sass {
|
|
815
766
|
if (operand->concrete_type() == Expression::NULL_VAL && dynamic_cast<Variable*>(u->operand())) {
|
816
767
|
u->operand(SASS_MEMORY_NEW(ctx.mem, String_Quoted, u->pstate(), ""));
|
817
768
|
}
|
818
|
-
|
769
|
+
// Never apply unary opertions on colors @see #2140
|
770
|
+
else if (operand->concrete_type() == Expression::COLOR) {
|
771
|
+
Color* c = dynamic_cast<Color*>(operand);
|
772
|
+
|
773
|
+
// Use the color name if this was eval with one
|
774
|
+
if (c->disp().length() > 0) {
|
775
|
+
operand = SASS_MEMORY_NEW(ctx.mem, String_Constant, operand->pstate(), c->disp());
|
776
|
+
u->operand(operand);
|
777
|
+
}
|
778
|
+
}
|
779
|
+
else {
|
780
|
+
u->operand(operand);
|
781
|
+
}
|
782
|
+
|
819
783
|
String_Constant* result = SASS_MEMORY_NEW(ctx.mem, String_Quoted,
|
820
784
|
u->pstate(),
|
821
785
|
u->inspect());
|
@@ -837,26 +801,12 @@ namespace Sass {
|
|
837
801
|
std::string full_name(name + "[f]");
|
838
802
|
Arguments* args = SASS_MEMORY_NEW(ctx.mem, Arguments, *c->arguments());
|
839
803
|
|
840
|
-
// handle call here if valid arg
|
841
|
-
// otherwise we eval arguments to early
|
842
|
-
if (name == "call" && args->length() > 0) {
|
843
|
-
Expression* redirect = args->at(0)->perform(this);
|
844
|
-
args->erase(args->begin());
|
845
|
-
Function_Call* lit = SASS_MEMORY_NEW(ctx.mem, Function_Call,
|
846
|
-
c->pstate(),
|
847
|
-
unquote(redirect->to_string()),
|
848
|
-
args);
|
849
|
-
return operator()(lit);
|
850
|
-
}
|
851
|
-
|
852
804
|
Env* env = environment();
|
853
805
|
if (!env->has(full_name)) {
|
854
806
|
if (!env->has("*[f]")) {
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
b->reset_whitespace();
|
859
|
-
arg->is_delayed(b->can_delay()); // delay
|
807
|
+
for (Argument* arg : args->elements()) {
|
808
|
+
if (List* ls = dynamic_cast<List*>(arg->value())) {
|
809
|
+
if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate());
|
860
810
|
}
|
861
811
|
}
|
862
812
|
args = static_cast<Arguments*>(args->perform(this));
|
@@ -878,16 +828,26 @@ namespace Sass {
|
|
878
828
|
}
|
879
829
|
}
|
880
830
|
|
831
|
+
// further delay for calls
|
832
|
+
if (full_name != "call[f]") {
|
833
|
+
args->set_delayed(false); // verified
|
834
|
+
}
|
881
835
|
if (full_name != "if[f]") {
|
882
836
|
args = static_cast<Arguments*>(args->perform(this));
|
883
837
|
}
|
884
|
-
|
885
838
|
Definition* def = static_cast<Definition*>((*env)[full_name]);
|
886
839
|
|
887
840
|
if (def->is_overload_stub()) {
|
888
841
|
std::stringstream ss;
|
889
|
-
|
890
|
-
|
842
|
+
size_t L = args->length();
|
843
|
+
// account for rest arguments
|
844
|
+
if (args->has_rest_argument() && args->length() > 0) {
|
845
|
+
// get the rest arguments list
|
846
|
+
List* rest = dynamic_cast<List*>(args->last()->value());
|
847
|
+
// arguments before rest argument plus rest
|
848
|
+
if (rest) L += rest->length() - 1;
|
849
|
+
}
|
850
|
+
ss << full_name << L;
|
891
851
|
full_name = ss.str();
|
892
852
|
std::string resolved_name(full_name);
|
893
853
|
if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate());
|
@@ -908,8 +868,8 @@ namespace Sass {
|
|
908
868
|
Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
|
909
869
|
exp.backtrace_stack.push_back(&here);
|
910
870
|
// eval the body if user-defined or special, invoke underlying CPP function if native
|
911
|
-
if (body && !Prelexer::re_special_fun(
|
912
|
-
else if (func) { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace()); }
|
871
|
+
if (body && !Prelexer::re_special_fun(name.c_str())) { result = body->perform(this); }
|
872
|
+
else if (func) { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace(), exp.selector_stack); }
|
913
873
|
if (!result) error(std::string("Function ") + c->name() + " did not return a value", c->pstate());
|
914
874
|
exp.backtrace_stack.pop_back();
|
915
875
|
}
|
@@ -960,8 +920,7 @@ namespace Sass {
|
|
960
920
|
if (result->pstate().file == std::string::npos)
|
961
921
|
result->pstate(c->pstate());
|
962
922
|
|
963
|
-
result
|
964
|
-
if (!result->is_delayed()) result = result->perform(this);
|
923
|
+
result = result->perform(this);
|
965
924
|
result->is_interpolant(c->is_interpolant());
|
966
925
|
exp.env_stack.pop_back();
|
967
926
|
return result;
|
@@ -990,35 +949,13 @@ namespace Sass {
|
|
990
949
|
value = SASS_MEMORY_NEW(ctx.mem, Number, *static_cast<Number*>(value));
|
991
950
|
static_cast<Number*>(value)->zero(true);
|
992
951
|
}
|
993
|
-
else if (value->concrete_type() == Expression::STRING) {
|
994
|
-
if (auto str = dynamic_cast<String_Quoted*>(value)) {
|
995
|
-
value = SASS_MEMORY_NEW(ctx.mem, String_Quoted, *str);
|
996
|
-
} else if (auto str = dynamic_cast<String_Constant*>(value)) {
|
997
|
-
value = SASS_MEMORY_NEW(ctx.mem, String_Quoted, str->pstate(), str->value());
|
998
|
-
}
|
999
|
-
}
|
1000
|
-
else if (value->concrete_type() == Expression::LIST) {
|
1001
|
-
value = SASS_MEMORY_NEW(ctx.mem, List, *static_cast<List*>(value));
|
1002
|
-
}
|
1003
|
-
else if (value->concrete_type() == Expression::MAP) {
|
1004
|
-
value = SASS_MEMORY_NEW(ctx.mem, Map, *static_cast<Map*>(value));
|
1005
|
-
}
|
1006
|
-
else if (value->concrete_type() == Expression::BOOLEAN) {
|
1007
|
-
value = SASS_MEMORY_NEW(ctx.mem, Boolean, *static_cast<Boolean*>(value));
|
1008
|
-
}
|
1009
|
-
else if (value->concrete_type() == Expression::COLOR) {
|
1010
|
-
value = SASS_MEMORY_NEW(ctx.mem, Color, *static_cast<Color*>(value));
|
1011
|
-
}
|
1012
|
-
else if (value->concrete_type() == Expression::NULL_VAL) {
|
1013
|
-
value = SASS_MEMORY_NEW(ctx.mem, Null, value->pstate());
|
1014
|
-
}
|
1015
|
-
else if (value->concrete_type() == Expression::SELECTOR) {
|
1016
|
-
value = value->perform(this); // ->perform(&listize);
|
1017
|
-
}
|
1018
952
|
|
1019
953
|
value->is_interpolant(v->is_interpolant());
|
1020
|
-
value->is_expanded(false);
|
1021
|
-
|
954
|
+
if (force) value->is_expanded(false);
|
955
|
+
value->set_delayed(false); // verified
|
956
|
+
value = value->perform(this);
|
957
|
+
if(!force) (*env)[name] = value;
|
958
|
+
return value;
|
1022
959
|
}
|
1023
960
|
|
1024
961
|
Expression* Eval::operator()(Textual* t)
|
@@ -1095,6 +1032,11 @@ namespace Sass {
|
|
1095
1032
|
return result;
|
1096
1033
|
}
|
1097
1034
|
|
1035
|
+
Expression* Eval::operator()(Color* c)
|
1036
|
+
{
|
1037
|
+
return c;
|
1038
|
+
}
|
1039
|
+
|
1098
1040
|
Expression* Eval::operator()(Number* n)
|
1099
1041
|
{
|
1100
1042
|
return n;
|
@@ -1153,14 +1095,23 @@ namespace Sass {
|
|
1153
1095
|
bool is_null = dynamic_cast<Null*>(item) != 0; // rl != ""
|
1154
1096
|
if (!is_null) *ll << SASS_MEMORY_NEW(ctx.mem, String_Quoted, item->pstate(), rl);
|
1155
1097
|
}
|
1156
|
-
|
1098
|
+
// Check indicates that we probably should not get a list
|
1099
|
+
// here. Normally single list items are already unwrapped.
|
1100
|
+
if (l->size() > 1) {
|
1101
|
+
// string_to_output would fail "#{'_\a' '_\a'}";
|
1102
|
+
std::string str(ll->to_string(ctx.c_options));
|
1103
|
+
newline_to_space(str); // replace directly
|
1104
|
+
res += str; // append to result string
|
1105
|
+
} else {
|
1106
|
+
res += (ll->to_string(ctx.c_options));
|
1107
|
+
}
|
1157
1108
|
ll->is_interpolant(l->is_interpolant());
|
1158
1109
|
}
|
1159
1110
|
|
1160
1111
|
// Value
|
1161
1112
|
// Textual
|
1162
1113
|
// Function_Call
|
1163
|
-
//
|
1114
|
+
// CommaSequence_Selector
|
1164
1115
|
// String_Quoted
|
1165
1116
|
// String_Constant
|
1166
1117
|
// Parent_Selector
|
@@ -1201,7 +1152,7 @@ namespace Sass {
|
|
1201
1152
|
bool is_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
|
1202
1153
|
if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
1203
1154
|
else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
1204
|
-
Expression* ex = (*s)[i]->
|
1155
|
+
Expression* ex = (*s)[i]->perform(this);
|
1205
1156
|
interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
|
1206
1157
|
was_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
|
1207
1158
|
was_interpolant = (*s)[i]->is_interpolant();
|
@@ -1211,7 +1162,8 @@ namespace Sass {
|
|
1211
1162
|
if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(ctx.mem, Null, s->pstate());
|
1212
1163
|
return SASS_MEMORY_NEW(ctx.mem, String_Constant, s->pstate(), res);
|
1213
1164
|
}
|
1214
|
-
|
1165
|
+
// string schema seems to have a special unquoting behavior (also handles "nested" quotes)
|
1166
|
+
String_Quoted* str = SASS_MEMORY_NEW(ctx.mem, String_Quoted, s->pstate(), res, 0, false, false, false);
|
1215
1167
|
// if (s->is_interpolant()) str->quote_mark(0);
|
1216
1168
|
// String_Constant* str = SASS_MEMORY_NEW(ctx.mem, String_Constant, s->pstate(), res);
|
1217
1169
|
if (str->quote_mark()) str->quote_mark('*');
|
@@ -1227,6 +1179,7 @@ namespace Sass {
|
|
1227
1179
|
Color* c = SASS_MEMORY_NEW(ctx.mem, Color, *name_to_color(s->value()));
|
1228
1180
|
c->pstate(s->pstate());
|
1229
1181
|
c->disp(s->value());
|
1182
|
+
c->is_delayed(true);
|
1230
1183
|
return c;
|
1231
1184
|
}
|
1232
1185
|
return s;
|
@@ -1343,10 +1296,7 @@ namespace Sass {
|
|
1343
1296
|
Expression* Eval::operator()(Argument* a)
|
1344
1297
|
{
|
1345
1298
|
Expression* val = a->value();
|
1346
|
-
// delay missin function arguments?
|
1347
|
-
val->is_delayed(a->is_delayed());
|
1348
1299
|
val = val->perform(this);
|
1349
|
-
val->is_delayed(false);
|
1350
1300
|
|
1351
1301
|
bool is_rest_argument = a->is_rest_argument();
|
1352
1302
|
bool is_keyword_argument = a->is_keyword_argument();
|
@@ -1606,12 +1556,8 @@ namespace Sass {
|
|
1606
1556
|
if ( (sep == "") /* &&
|
1607
1557
|
(sep != "/" || !rqstr || !rqstr->quote_mark()) */
|
1608
1558
|
) {
|
1609
|
-
|
1610
|
-
|
1611
|
-
if (quote_mark && quote_mark != '*') {
|
1612
|
-
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(), quote_mark + unq + quote_mark);
|
1613
|
-
}
|
1614
|
-
return SASS_MEMORY_NEW(mem, String_Quoted, lhs.pstate(), lstr + sep + rstr);
|
1559
|
+
// create a new string that might be quoted on output (but do not unquote what we pass)
|
1560
|
+
return SASS_MEMORY_NEW(mem, String_Quoted, pstate ? *pstate : lhs.pstate(), lstr + rstr, 0, false, true);
|
1615
1561
|
}
|
1616
1562
|
|
1617
1563
|
if (sep != "" && !delayed) {
|
@@ -1622,10 +1568,9 @@ namespace Sass {
|
|
1622
1568
|
if (op == Sass_OP::SUB || op == Sass_OP::DIV) {
|
1623
1569
|
if (lqstr && lqstr->quote_mark()) lstr = quote(lstr);
|
1624
1570
|
if (rqstr && rqstr->quote_mark()) rstr = quote(rstr);
|
1625
|
-
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(), lstr + sep + rstr);
|
1626
1571
|
}
|
1627
1572
|
|
1628
|
-
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(),
|
1573
|
+
return SASS_MEMORY_NEW(mem, String_Constant, pstate ? *pstate : lhs.pstate(), lstr + sep + rstr);
|
1629
1574
|
}
|
1630
1575
|
|
1631
1576
|
Expression* cval_to_astnode(Memory_Manager& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate)
|
@@ -1679,10 +1624,10 @@ namespace Sass {
|
|
1679
1624
|
return e;
|
1680
1625
|
}
|
1681
1626
|
|
1682
|
-
|
1627
|
+
CommaSequence_Selector* Eval::operator()(CommaSequence_Selector* s)
|
1683
1628
|
{
|
1684
|
-
std::vector<
|
1685
|
-
|
1629
|
+
std::vector<CommaSequence_Selector*> rv;
|
1630
|
+
CommaSequence_Selector* sl = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, s->pstate());
|
1686
1631
|
sl->is_optional(s->is_optional());
|
1687
1632
|
sl->media_block(s->media_block());
|
1688
1633
|
sl->is_optional(s->is_optional());
|
@@ -1712,9 +1657,10 @@ namespace Sass {
|
|
1712
1657
|
}
|
1713
1658
|
|
1714
1659
|
|
1715
|
-
|
1660
|
+
CommaSequence_Selector* Eval::operator()(Sequence_Selector* s)
|
1716
1661
|
{
|
1717
|
-
|
1662
|
+
bool implicit_parent = !exp.old_at_root_without_rule;
|
1663
|
+
return s->resolve_parent_refs(ctx, selector(), implicit_parent);
|
1718
1664
|
|
1719
1665
|
}
|
1720
1666
|
|
@@ -1728,21 +1674,21 @@ namespace Sass {
|
|
1728
1674
|
return ss;
|
1729
1675
|
}
|
1730
1676
|
|
1731
|
-
|
1677
|
+
CommaSequence_Selector* Eval::operator()(Selector_Schema* s)
|
1732
1678
|
{
|
1733
1679
|
// the parser will look for a brace to end the selector
|
1734
1680
|
std::string result_str(s->contents()->perform(this)->to_string(ctx.c_options));
|
1735
1681
|
result_str = unquote(Util::rtrim(result_str)) + "\n{";
|
1736
1682
|
Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
|
1737
1683
|
p.last_media_block = s->media_block();
|
1738
|
-
|
1684
|
+
CommaSequence_Selector* sl = p.parse_selector_list(exp.block_stack.back()->is_root());
|
1739
1685
|
if (s->has_parent_ref()) sl->remove_parent_selectors();
|
1740
1686
|
return operator()(sl);
|
1741
1687
|
}
|
1742
1688
|
|
1743
1689
|
Expression* Eval::operator()(Parent_Selector* p)
|
1744
1690
|
{
|
1745
|
-
|
1691
|
+
CommaSequence_Selector* pr = selector();
|
1746
1692
|
if (pr) {
|
1747
1693
|
exp.selector_stack.pop_back();
|
1748
1694
|
pr = operator()(pr);
|