@@ -47,14 +47,40 @@ namespace Sass {
47
47
48
48
// If the current parameter is the rest parameter, process and break the loop
49
49
if (p->is_rest_parameter ()) {
50
+ // The next argument by coincidence provides a rest argument
50
51
if (a->is_rest_argument ()) {
51
- // rest param and rest arg -- just add one to the other
52
- if (env->has_local (p->name ())) {
53
- *static_cast <List*>(env->local_frame ()[p->name ()])
54
- += static_cast <List*>(a->value ());
52
+ // We should always get a list for rest arguments
53
+ if (List* rest = dynamic_cast <List*>(a->value ())) {
54
+ // arg contains a list
55
+ List* args = rest;
56
+ // make sure it's an arglist
57
+ if (rest->is_arglist ()) {
58
+ // can pass it through as it was
59
+ env->local_frame ()[p->name ()] = args;
60
+ }
61
+ // create a new list and wrap each item as an argument
62
+ // otherwise we will not be able to fetch it again
63
+ else {
64
+ // create a new list object for wrapped items
65
+ List* arglist = new (ctx.mem ) List (p->pstate (),
66
+ 0 ,
67
+ rest->separator (),
68
+ true );
69
+ // wrap each item from list as an argument
70
+ for (Expression* item : rest->elements ()) {
71
+ (*arglist) << new (ctx.mem ) Argument (item->pstate (),
72
+ item,
73
+ " " ,
74
+ false ,
75
+ false );
76
+ }
77
+ // assign new arglist to environment
78
+ env->local_frame ()[p->name ()] = arglist;
79
+ }
55
80
}
81
+ // invalid state
56
82
else {
57
- env-> local_frame ()[p-> name ()] = a-> value ( );
83
+ throw runtime_error ( " invalid state " );
58
84
}
59
85
} else if (a->is_keyword_argument ()) {
60
86
@@ -72,27 +98,36 @@ namespace Sass {
72
98
73
99
} else {
74
100
75
- // copy all remaining arguments into the rest parameter, preserving names
101
+ // create a new list object for wrapped items
76
102
List* arglist = new (ctx.mem ) List (p->pstate (),
77
103
0 ,
78
104
List::COMMA,
79
105
true );
80
- env-> local_frame ()[p-> name ()] = arglist;
106
+ // consume the next args
81
107
while (ia < LA) {
82
- a = (*as)[ia];
108
+ // get and post inc
109
+ a = (*as)[ia++];
110
+ // wrap current argument into new object
111
+ (*arglist) << new (ctx.mem ) Argument (a->pstate (),
112
+ a->value (),
113
+ a->name (),
114
+ false );
115
+ // check if we have rest argument
83
116
if (a->is_rest_argument ()) {
117
+ // preserve the list separator from rest args
84
118
if (List* rest = dynamic_cast <List*>(a->value ())) {
85
119
arglist->separator (rest->separator ());
86
120
}
121
+ // no more arguments
122
+ break ;
87
123
}
88
- (*arglist) << new (ctx.mem ) Argument (a->pstate (),
89
- a->value (),
90
- a->name (),
91
- false );
92
- ++ia;
93
124
}
125
+ // assign new arglist to environment
126
+ env->local_frame ()[p->name ()] = arglist;
94
127
}
128
+ // consumed parameter
95
129
++ip;
130
+ // no more paramaters
96
131
break ;
97
132
}
98
133
@@ -167,6 +202,7 @@ namespace Sass {
167
202
env->local_frame ()[a->name ()] = a->value ();
168
203
}
169
204
}
205
+ // EO while ia
170
206
171
207
// If we make it here, we're out of args but may have leftover params.
172
208
// That's only okay if they have default values, or were already bound by
0 commit comments