From 0e9279c513ad6cd2ceb736fabe1637d393e831e9 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Mon, 11 Jan 2016 04:25:39 +0100 Subject: [PATCH] Fix check for wrong import directives placement --- src/expand.cpp | 17 +++++++++++++++++ src/expand.hpp | 1 + src/operation.hpp | 2 +- src/parser.cpp | 3 --- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/expand.cpp b/src/expand.cpp index 9512f18031..cb385e54c6 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -20,6 +20,7 @@ namespace Sass { eval(Eval(*this)), env_stack(std::vector()), block_stack(std::vector()), + call_stack(std::vector()), property_stack(std::vector()), selector_stack(std::vector()), backtrace_stack(std::vector()), @@ -28,6 +29,7 @@ namespace Sass { env_stack.push_back(0); env_stack.push_back(env); block_stack.push_back(0); + call_stack.push_back(0); // import_stack.push_back(0); property_stack.push_back(0); selector_stack.push_back(0); @@ -327,6 +329,11 @@ namespace Sass { Statement* Expand::operator()(Import_Stub* i) { + // get parent node from call stack + AST_Node* parent = call_stack.back(); + if (parent && dynamic_cast(parent) == NULL) { + error("Import directives may not be used within control directives or mixins.", i->pstate()); + } // we don't seem to need that actually afterall Sass_Import_Entry import = sass_make_import( i->imp_path().c_str(), @@ -372,6 +379,7 @@ namespace Sass { { Env env(environment(), true); env_stack.push_back(&env); + call_stack.push_back(i); if (*i->predicate()->perform(&eval)) { append_block(i->block()); } @@ -379,6 +387,7 @@ namespace Sass { Block* alt = i->alternative(); if (alt) append_block(alt); } + call_stack.pop_back(); env_stack.pop_back(); return 0; } @@ -410,6 +419,7 @@ namespace Sass { // only create iterator once in this environment Env env(environment(), true); env_stack.push_back(&env); + call_stack.push_back(f); Number* it = SASS_MEMORY_NEW(env.mem, Number, low->pstate(), start, sass_end->unit()); env.set_local(variable, it); Block* body = f->block(); @@ -432,6 +442,7 @@ namespace Sass { append_block(body); } } + call_stack.pop_back(); env_stack.pop_back(); return 0; } @@ -457,6 +468,7 @@ namespace Sass { // remember variables and then reset them Env env(environment(), true); env_stack.push_back(&env); + call_stack.push_back(e); Block* body = e->block(); if (map) { @@ -511,6 +523,7 @@ namespace Sass { append_block(body); } } + call_stack.pop_back(); env_stack.pop_back(); return 0; } @@ -521,9 +534,11 @@ namespace Sass { Block* body = w->block(); Env env(environment(), true); env_stack.push_back(&env); + call_stack.push_back(w); while (*pred->perform(&eval)) { append_block(body); } + call_stack.pop_back(); env_stack.pop_back(); return 0; } @@ -693,10 +708,12 @@ namespace Sass { // process and add to last block on stack inline void Expand::append_block(Block* b) { + if (b->is_root()) call_stack.push_back(b); for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* ith = (*b)[i]->perform(this); if (ith) *block_stack.back() << ith; } + if (b->is_root()) call_stack.pop_back(); } } diff --git a/src/expand.hpp b/src/expand.hpp index ae789bf5fe..2c4d846952 100644 --- a/src/expand.hpp +++ b/src/expand.hpp @@ -30,6 +30,7 @@ namespace Sass { // it's easier to work with vectors std::vector env_stack; std::vector block_stack; + std::vector call_stack; std::vector property_stack; std::vector selector_stack; std::vectorbacktrace_stack; diff --git a/src/operation.hpp b/src/operation.hpp index 2cc850ebdf..47adf6bafc 100644 --- a/src/operation.hpp +++ b/src/operation.hpp @@ -15,7 +15,7 @@ namespace Sass { virtual T operator()(Ruleset* x) = 0; virtual T operator()(Propset* x) = 0; virtual T operator()(Bubble* x) = 0; - virtual T operator()(Supports_Block* x) = 0; + virtual T operator()(Supports_Block* x) = 0; virtual T operator()(Media_Block* x) = 0; virtual T operator()(At_Root_Block* x) = 0; virtual T operator()(At_Rule* x) = 0; diff --git a/src/parser.cpp b/src/parser.cpp index 32c072001f..c540eacff7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -205,9 +205,6 @@ namespace Sass { // parse imports to process later else if (lex < kwd_import >(true)) { - if (stack.back() == mixin_def || stack.back() == function_def) { - error("Import directives may not be used within control directives or mixins.", pstate); - } Import* imp = parse_import(); // if it is a url, we only add the statement if (!imp->urls().empty()) (*block) << imp;