Skip to content

Commit a672dd9

Browse files
committed
fix: maintain outer context
1 parent 466fa7d commit a672dd9

File tree

2 files changed

+34
-48
lines changed

2 files changed

+34
-48
lines changed

domUtil/template.js

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,22 @@ function getValueFromContext(exp, context) {
6161
function extractElseif(ifExps, sourcesInsideBlock) {
6262
var exps = [ifExps];
6363
var sourcesInsideIf = [];
64-
64+
var otherIfCount = 0;
6565
var start = 0;
66-
var i, len, source;
67-
68-
for (i = 0, len = sourcesInsideBlock.length; i < len; i += 1) {
69-
source = sourcesInsideBlock[i];
7066

71-
if (source.indexOf('elseif') > -1 || source === 'else') {
67+
// eslint-disable-next-line complexity
68+
forEach(sourcesInsideBlock, function(source, index) {
69+
if (source.indexOf('if') === 0) {
70+
otherIfCount += 1;
71+
} else if (source === '/if') {
72+
otherIfCount -= 1;
73+
} else if (!otherIfCount && (source.indexOf('elseif') === 0 || source === 'else')) {
7274
exps.push(source === 'else' ? ['true'] : source.split(' ').slice(1));
73-
sourcesInsideIf.push(sourcesInsideBlock.slice(start, i));
74-
start = i + 1;
75+
sourcesInsideIf.push(sourcesInsideBlock.slice(start, index));
76+
start = index + 1;
7577
}
76-
}
78+
});
79+
7780
sourcesInsideIf.push(sourcesInsideBlock.slice(start));
7881

7982
return {
@@ -124,9 +127,9 @@ function handleEach(exps, sourcesInsideBlock, context) {
124127
forEach(collection, function(item, key) {
125128
additionalContext[additionalKey] = key;
126129
additionalContext['@this'] = item;
127-
extend(additionalContext, context);
130+
extend(context, additionalContext);
128131

129-
result += compile(sourcesInsideBlock.slice(), additionalContext);
132+
result += compile(sourcesInsideBlock.slice(), context);
130133
});
131134

132135
return result;
@@ -148,7 +151,7 @@ function handleWith(exps, sourcesInsideBlock, context) {
148151
var additionalContext = {};
149152
additionalContext[alias] = result;
150153

151-
return compile(sourcesInsideBlock, extend(additionalContext, context)) || '';
154+
return compile(sourcesInsideBlock, extend(context, additionalContext)) || '';
152155
}
153156

154157
/**
@@ -166,25 +169,6 @@ function extractSourcesInsideBlock(sources, start, end) {
166169
return sourcesInsideBlock;
167170
}
168171

169-
/**
170-
* Concatenate the strings between previous and next of the base string in place.
171-
* @param {Array.<string>} sources - array of sources
172-
* @param {number} index - index of base string
173-
* @private
174-
*/
175-
function concatPrevAndNextString(source, index) {
176-
var start = Math.max(index - 1, 0);
177-
var end = Math.min(index + 1, source.length - 1);
178-
var deletedCount = end - start + 1;
179-
var result = source.splice(start, deletedCount).join('');
180-
181-
if (deletedCount < 3) {
182-
source.splice(start, 0, '', result);
183-
} else {
184-
source.splice(start, 0, result);
185-
}
186-
}
187-
188172
/**
189173
* Handle block helper function
190174
* @param {string} helperKeyword - helper keyword (ex. if, each, with)
@@ -195,37 +179,34 @@ function concatPrevAndNextString(source, index) {
195179
*/
196180
function handleBlockHelper(helperKeyword, sourcesToEnd, context) {
197181
var executeBlockHelper = BLOCK_HELPERS[helperKeyword];
198-
var startBlockIndices = [];
199-
var helperCount = 0;
200-
var index = 0;
182+
var helperCount = 1;
183+
var startBlockIndex = 0;
184+
var endBlockIndex;
185+
var index = startBlockIndex + EXPRESSION_INTERVAL;
201186
var expression = sourcesToEnd[index];
202-
var startBlockIndex;
203187

204-
do {
188+
while (helperCount && isString(expression)) {
205189
if (expression.indexOf(helperKeyword) === 0) {
206190
helperCount += 1;
207-
startBlockIndices.push(index);
208191
} else if (expression.indexOf('/' + helperKeyword) === 0) {
209192
helperCount -= 1;
210-
startBlockIndex = startBlockIndices.pop();
211-
212-
sourcesToEnd[startBlockIndex] = executeBlockHelper(
213-
sourcesToEnd[startBlockIndex].split(' ').slice(1),
214-
extractSourcesInsideBlock(sourcesToEnd, startBlockIndex, index),
215-
context
216-
);
217-
concatPrevAndNextString(sourcesToEnd, startBlockIndex);
218-
index = startBlockIndex - EXPRESSION_INTERVAL;
193+
endBlockIndex = index;
219194
}
220195

221196
index += EXPRESSION_INTERVAL;
222197
expression = sourcesToEnd[index];
223-
} while (helperCount && isString(expression));
198+
}
224199

225200
if (helperCount) {
226201
throw Error(helperKeyword + ' needs {{/' + helperKeyword + '}} expression.');
227202
}
228203

204+
sourcesToEnd[startBlockIndex] = executeBlockHelper(
205+
sourcesToEnd[startBlockIndex].split(' ').slice(1),
206+
extractSourcesInsideBlock(sourcesToEnd, startBlockIndex, endBlockIndex),
207+
context
208+
);
209+
229210
return sourcesToEnd;
230211
}
231212

test/template.spec.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ describe('block helper', function() {
9494
expect(function() {
9595
return template('{{each arr}}', {});
9696
}).toThrowError('each needs {{/each}} expression.');
97-
9897
expect(function() {
9998
return template('{{with 1 as one}}', {});
10099
}).toThrowError('with needs {{/with}} expression.');
@@ -231,6 +230,12 @@ describe('{{each ...}} @this @index @key {{/each}}', function() {
231230
second: [4, 5, 6]
232231
};
233232
expect(template(source, context)).toBe('456456456');
233+
234+
source = '{{each doubleArr}}{{each @this}}{{@this}}{{/each}}{{/each}}';
235+
context = {
236+
doubleArr: [[1, 2, 3], [4, 5, 6]]
237+
};
238+
expect(template(source, context)).toBe('123456');
234239
});
235240
});
236241

0 commit comments

Comments
 (0)