Skip to content

Commit ba9d706

Browse files
mrmlncmichael-ciniawsky
authored andcommitted
perf(index): Make a copy of the tree only once
1 parent 7495642 commit ba9d706

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

lib/index.js

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,27 @@ function walk (opts, nodes) {
176176
throw new Error('You must provide at least one loop argument')
177177
}
178178

179+
// converts nodes to a string. These nodes will be changed within the loop
180+
const treeString = JSON.stringify(node.content)
181+
const keys = loopParams.keys
182+
183+
// creates a copy of the keys that will be changed within the loop
184+
const localsBackup = makeBackupLoopKeys(keys[0], keys[1], opts.locals)
185+
179186
// run the loop, different types of loops for arrays and objects
180187
if (Array.isArray(target)) {
181188
for (let index = 0; index < target.length; index++) {
182-
m.push(executeLoop(loopParams.keys, target[index], index, node))
189+
m.push(executeLoop(keys, target[index], index, opts.locals, treeString))
183190
}
184191
} else {
185192
for (let key in target) {
186-
m.push(executeLoop(loopParams.keys, target[key], key, node))
193+
m.push(executeLoop(keys, target[key], key, opts.locals, treeString))
187194
}
188195
}
189196

197+
// returns the original keys values that was changed within the loop
198+
opts.locals = revertBackupedLocals(keys[0], keys[1], opts.locals, localsBackup)
199+
190200
// return directly out of the loop, which will skip the "each" tag
191201
return m
192202
}
@@ -258,19 +268,45 @@ function parseLoopStatement (input) {
258268
}
259269
}
260270

271+
/**
272+
* Creates a backup of keys within the loop
273+
*/
274+
function makeBackupLoopKeys (p1, p2, locals) {
275+
let backup = {}
276+
if (p1 && data.locals.hasOwnProperty(p1)) backup[p1] = data.locals[p1]
277+
if (p2 && data.locals.hasOwnProperty(p2)) backup[p2] = data.locals[p2]
278+
279+
return backup
280+
}
281+
282+
/**
283+
* Returns the original keys values
284+
*/
285+
function revertBackupedLocals (p1, p2, locals, backup) {
286+
// Remove loop keys from locals
287+
delete locals[p1]
288+
delete locals[p2]
289+
290+
// Revert copied keys
291+
if (p1 && backup.hasOwnProperty(p1)) locals[p1] = backup[p1]
292+
if (p2 && backup.hasOwnProperty(p2)) locals[p2] = backup[p2]
293+
294+
return locals
295+
}
296+
261297
/**
262298
* Creates a set of local variables within the loop, and evaluates all nodes
263299
* within the loop, returning their contents
264300
*/
265-
function executeLoop (loopParams, p1, p2, node) {
301+
function executeLoop (loopParams, p1, p2, locals, treeString) {
266302
// two loop locals are allowed
267303
// - for arrays it's the current value and the index
268304
// - for objects, it's the value and the key
269-
const scopedLocals = {}
305+
const scopedLocals = locals
270306
scopedLocals[loopParams[0]] = p1
271307
if (loopParams[1]) scopedLocals[loopParams[1]] = p2
272308

273-
return executeScoped(scopedLocals, node)
309+
return walk({ locals: scopedLocals }, JSON.parse(treeString))
274310
}
275311

276312
/**

0 commit comments

Comments
 (0)