diff --git a/blocks-common/i-bem/__html/i-bem__html.bemhtml b/blocks-common/i-bem/__html/i-bem__html.bemhtml index 8cf134d2..258b9767 100644 --- a/blocks-common/i-bem/__html/i-bem__html.bemhtml +++ b/blocks-common/i-bem/__html/i-bem__html.bemhtml @@ -186,6 +186,7 @@ function BEMContext(apply_) { this._start = true; this._listLength = 0; this._notNewList = false; + this._inside = false; this.position = 0; }; @@ -266,11 +267,22 @@ BEMContext.prototype.generateId = function generateId() { return this.identify(this.ctx); }; +function slowApply() { + var ctx = new BEMContext(apply); + ctx.reinit(this); + ctx.apply(); + return ctx._buf.join(''); +}; + // Wrap xjst's apply and export our own var ctx = new BEMContext(apply); exports.apply = BEMContext.apply = function _apply() { + if (ctx._inside) return slowApply.call(this); + + ctx._inside = true; ctx.reinit(this); ctx.apply(); + ctx._inside = false; return ctx._buf.join(''); }; }(); diff --git a/blocks-common/i-bem/__html/test/files/i-bem/re-entrant.bemhtml b/blocks-common/i-bem/__html/test/files/i-bem/re-entrant.bemhtml new file mode 100644 index 00000000..7e8e90f5 --- /dev/null +++ b/blocks-common/i-bem/__html/test/files/i-bem/re-entrant.bemhtml @@ -0,0 +1,9 @@ +block b1, content: { + return this.invalid || 'ok'; +} + +block b2, content: { + local(this.invalid = 'bye') { + throw new Error('Oh god'); + } +} diff --git a/blocks-common/i-bem/__html/test/i-bem-test.js b/blocks-common/i-bem/__html/test/i-bem-test.js index bfe3e64a..ec3462a0 100644 --- a/blocks-common/i-bem/__html/test/i-bem-test.js +++ b/blocks-common/i-bem/__html/test/i-bem-test.js @@ -48,4 +48,12 @@ suite('i-bem block and others', function() { unit('applyNext in content regression #289', 'gh-289'); unit('mods redefinition #550', 'gh-550'); unit('block with escaping this', 'escaping-this'); + + test('re-entrance', function() { + var t = bemhtml.compile(iBem + readFile('i-bem/re-entrant.bemhtml')); + assert.throws(function() { + t.call({ block: 'b2' }); + }); + assert.equal(t.call({ block: 'b1' }), '