Skip to content

Commit

Permalink
Merge pull request #99 from kethinov/0.4.2
Browse files Browse the repository at this point in the history
Fix for circular references in models (closes #98)
  • Loading branch information
kethinov authored Feb 6, 2017
2 parents 150e411 + 707fdb1 commit 3d87dc3
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "teddy",
"description": "Teddy Templating Engine",
"author": "Eric Newport <[email protected]>",
"version": "0.4.1",
"version": "0.4.2",
"homepage": "https://github.com/kethinov/teddy",
"license": "CC-BY-4.0",
"main": "teddy.js",
Expand Down
29 changes: 25 additions & 4 deletions teddy.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,16 +277,22 @@
var renders = teddy.renderedTemplates[template],
i,
l,
render;
render,
stringyModel,
renderStringyModel;
if (renders) {
l = renders.length;
}
else {
return;
}
jsonStringifyCache = [];
stringyModel = JSON.stringify(model, jsonStringifyRemoveCircularReferences)
for (i = 0; i < l; i++) {
render = renders[i];
if (JSON.stringify(render.model) === JSON.stringify(model)) {
jsonStringifyCache = [];
renderStringyModel = JSON.stringify(render.model, jsonStringifyRemoveCircularReferences);
if (renderStringyModel === stringyModel) {
teddy.renderedTemplates[template].splice(i, 1);
}
}
Expand Down Expand Up @@ -315,6 +321,7 @@
renders,
render,
stringyModel,
renderStringyModel,
maxPasses = teddy.params.maxPasses,
maxPassesError = 'Render aborted due to max number of passes (' + maxPasses + ') exceeded; there is a possible infinite loop in your template logic.';

Expand Down Expand Up @@ -344,13 +351,16 @@

// return cached template if one exists
if (teddy.params.cacheRenders && teddy.templates[template] && (!teddy.params.cacheWhitelist || teddy.params.cacheWhitelist[template]) && teddy.params.cacheBlacklist.indexOf(template) < 0) {
stringyModel = JSON.stringify(model);
jsonStringifyCache = [];
stringyModel = JSON.stringify(model, jsonStringifyRemoveCircularReferences);
teddy.renderedTemplates[template] = teddy.renderedTemplates[template] || [];
renders = teddy.renderedTemplates[template];
l = renders.length;
for (i = 0; i < l; i++) {
render = renders[i];
if (JSON.stringify(render.model) === stringyModel) {
jsonStringifyCache = [];
renderStringyModel = JSON.stringify(render.model, jsonStringifyRemoveCircularReferences)
if (renderStringyModel === stringyModel) {

// move to last position in the array to mark it as most recently accessed
teddy.renderedTemplates[template].push(teddy.renderedTemplates[template].splice(i, 1)[0]);
Expand Down Expand Up @@ -1325,6 +1335,17 @@
}
}

function jsonStringifyRemoveCircularReferences(key, value) {
if (typeof value === 'object' && value !== null) {
if (jsonStringifyCache.indexOf(value) !== -1) {
// circular reference found, discard key
return;
}
jsonStringifyCache.push(value);
}
return value;
}

// expose as a CommonJS module
if (typeof module !== 'undefined' && module.exports) {
module.exports = teddy; // makes teddy requirable in server-side JS
Expand Down
1 change: 1 addition & 0 deletions test/client.html
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ <h2>Warning: these tests can only be run from a web server.</h2>
'includes/orphanedArgument.html',
'includes/inlineScriptTag.html',
'includes/argRedefineModelVar.html',
'includes/includeEscapeRegex.html',
'looping/emptyMarkupLoop.html',
'looping/largeDataSet.html',
'looping/loopArrayOfObjects.html',
Expand Down
3 changes: 3 additions & 0 deletions test/models/model.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
function makeModel() {
var model = {
letters: ['a', 'b', 'c'],
circular: {},
camelLetters: ['a', 'b', 'c'],
names: {jack: 'guy', jill: 'girl', hill: 'landscape'},
objects: [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}],
Expand Down Expand Up @@ -50,6 +51,8 @@ function makeModel() {
charList = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
cl = charList.length;

model.circular.circular = model.circular;

function randChars(n) {
var i, s = '';
for (i = 0; i < n; i++) {
Expand Down

0 comments on commit 3d87dc3

Please sign in to comment.