Skip to content

Commit 712bcaf

Browse files
committed
Merge pull request #1084 from mgreter/bugfix/issue_1081
Improve scope handling for variables
2 parents 39cae80 + 9bc24a9 commit 712bcaf

File tree

3 files changed

+96
-26
lines changed

3 files changed

+96
-26
lines changed

environment.hpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ namespace Sass {
104104
// see if we have a lexical we could update
105105
// either update already existing lexical value
106106
// or if flag is set, we create one if no lexical found
107-
void set_lexical(const string& key, T val, bool global = false)
107+
void set_lexical(const string& key, T val)
108108
{
109109
auto cur = this;
110110
while (cur->is_lexical()) {
@@ -114,11 +114,7 @@ namespace Sass {
114114
}
115115
cur = cur->parent_;
116116
}
117-
if (global) {
118-
set_global(key, val);
119-
} else {
120-
set_local(key, val);
121-
}
117+
set_local(key, val);
122118
}
123119

124120
// look on the full stack for key

eval.cpp

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,56 @@ namespace Sass {
6565
{
6666
string var(a->variable());
6767
if (a->is_global()) {
68-
env->set_global(var, a->value()->perform(this));
69-
}
70-
else if (a->is_default()) {
71-
if (env->has_lexical(var)) return 0;
72-
if (env->has_global(var)) {
73-
Expression* e = static_cast<Expression*>(env->get_global(var));
74-
if (e->concrete_type() == Expression::NULL_VAL) {
68+
if (a->is_default()) {
69+
if (env->has_global(var)) {
70+
Expression* e = dynamic_cast<Expression*>(env->get_global(var));
71+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
72+
env->set_global(var, a->value()->perform(this));
73+
}
74+
}
75+
else {
7576
env->set_global(var, a->value()->perform(this));
7677
}
77-
} else {
78+
}
79+
else {
7880
env->set_global(var, a->value()->perform(this));
7981
}
8082
}
83+
else if (a->is_default()) {
84+
if (env->has_lexical(var)) {
85+
auto cur = env;
86+
while (cur && cur->is_lexical()) {
87+
if (cur->has_local(var)) {
88+
if (AST_Node* node = cur->get_local(var)) {
89+
Expression* e = dynamic_cast<Expression*>(node);
90+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
91+
cur->set_local(var, a->value()->perform(this));
92+
}
93+
}
94+
else {
95+
throw runtime_error("Env not in sync");
96+
}
97+
return 0;
98+
}
99+
cur = cur->parent();
100+
}
101+
throw runtime_error("Env not in sync");
102+
}
103+
else if (env->has_global(var)) {
104+
if (AST_Node* node = env->get_global(var)) {
105+
Expression* e = dynamic_cast<Expression*>(node);
106+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
107+
env->set_global(var, a->value()->perform(this));
108+
}
109+
}
110+
}
111+
else if (env->is_lexical()) {
112+
env->set_local(var, a->value()->perform(this));
113+
}
114+
else {
115+
env->set_local(var, a->value()->perform(this));
116+
}
117+
}
81118
else {
82119
env->set_lexical(var, a->value()->perform(this));
83120
}
@@ -122,7 +159,7 @@ namespace Sass {
122159
double end = sass_end->value();
123160
// only create iterator once in this environment
124161
Number* it = new (env->mem) Number(low->pstate(), start, sass_end->unit());
125-
AST_Node* old_var = env->get_local(variable);
162+
AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
126163
env->set_local(variable, it);
127164
Block* body = f->block();
128165
Expression* val = 0;
@@ -174,7 +211,7 @@ namespace Sass {
174211
// remember variables and then reset them
175212
vector<AST_Node*> old_vars(variables.size());
176213
for (size_t i = 0, L = variables.size(); i < L; ++i) {
177-
old_vars[i] = env->get_local(variables[i]);
214+
old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
178215
env->set_local(variables[i], 0);
179216
}
180217
Block* body = e->block();

expand.cpp

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,56 @@ namespace Sass {
216216
string var(a->variable());
217217
Selector* p = selector_stack.size() <= 1 ? 0 : selector_stack.back();
218218
if (a->is_global()) {
219-
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
220-
}
221-
else if (a->is_default()) {
222-
if (env->has_lexical(var)) return 0;
223-
if (env->has_global(var)) {
224-
Expression* e = static_cast<Expression*>(env->get_global(var));
225-
if (e->concrete_type() == Expression::NULL_VAL) {
219+
if (a->is_default()) {
220+
if (env->has_global(var)) {
221+
Expression* e = dynamic_cast<Expression*>(env->get_global(var));
222+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
223+
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
224+
}
225+
}
226+
else {
226227
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
227228
}
228-
} else {
229+
}
230+
else {
229231
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
230232
}
231233
}
234+
else if (a->is_default()) {
235+
if (env->has_lexical(var)) {
236+
auto cur = env;
237+
while (cur && cur->is_lexical()) {
238+
if (cur->has_local(var)) {
239+
if (AST_Node* node = cur->get_local(var)) {
240+
Expression* e = dynamic_cast<Expression*>(node);
241+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
242+
cur->set_local(var, a->value()->perform(eval->with(p, env, backtrace)));
243+
}
244+
}
245+
else {
246+
throw runtime_error("Env not in sync");
247+
}
248+
return 0;
249+
}
250+
cur = cur->parent();
251+
}
252+
throw runtime_error("Env not in sync");
253+
}
254+
else if (env->has_global(var)) {
255+
if (AST_Node* node = env->get_global(var)) {
256+
Expression* e = dynamic_cast<Expression*>(node);
257+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
258+
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
259+
}
260+
}
261+
}
262+
else if (env->is_lexical()) {
263+
env->set_local(var, a->value()->perform(eval->with(p, env, backtrace)));
264+
}
265+
else {
266+
env->set_local(var, a->value()->perform(eval->with(p, env, backtrace)));
267+
}
268+
}
232269
else {
233270
env->set_lexical(var, a->value()->perform(eval->with(p, env, backtrace)));
234271
}
@@ -315,7 +352,7 @@ namespace Sass {
315352
double end = sass_end->value();
316353
// only create iterator once in this environment
317354
Number* it = new (env->mem) Number(low->pstate(), start, sass_end->unit());
318-
AST_Node* old_var = env->get_local(variable);
355+
AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
319356
env->set_local(variable, it);
320357
Block* body = f->block();
321358
if (start < end) {
@@ -364,7 +401,7 @@ namespace Sass {
364401
// remember variables and then reset them
365402
vector<AST_Node*> old_vars(variables.size());
366403
for (size_t i = 0, L = variables.size(); i < L; ++i) {
367-
old_vars[i] = env->get_local(variables[i]);
404+
old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
368405
env->set_local(variables[i], 0);
369406
}
370407
Block* body = e->block();

0 commit comments

Comments
 (0)