1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-10-20 10:17:38 +00:00

Detect recursion by tracking widget tree depth

The old recursion marker approach was very slow, and didn't catch test cases like editions/test/tiddlers/tests/data/transclude/Recursion.tid
This commit is contained in:
jeremy@jermolene.com
2022-05-12 16:26:33 +01:00
parent 413dc86d05
commit 904e30a0e2
5 changed files with 126 additions and 54 deletions

View File

@@ -62,25 +62,10 @@ TranscludeWidget.prototype.execute = function() {
parseTreeNodes = [{type: "text", text: plainText}];
break;
}
// Set context variables for recursion detection
var recursionMarker = this.makeRecursionMarker();
if(this.recursionMarker === "yes") {
this.setVariable("$transclusion",recursionMarker);
}
// Set the legacy transclusion context variables only if we're not transcluding a variable
if(!this.transcludeVariable) {
var legacyRecursionMarker = this.makeLegacyRecursionMarker();
this.setVariable("transclusion",legacyRecursionMarker);
}
// Check for recursion
if(target.parser) {
if(this.parentWidget && this.parentWidget.hasVariable("$transclusion",recursionMarker)) {
parseTreeNodes = [{type: "element", tag: "span", attributes: {
"class": {type: "string", value: "tc-error"}
}, children: [
{type: "text", text: $tw.language.getString("Error/RecursiveTransclusion")}
]}];
}
var recursionMarker = this.makeRecursionMarker();
this.setVariable("transclusion",recursionMarker);
}
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
@@ -335,29 +320,10 @@ TranscludeWidget.prototype.getTransclusionSlotValue = function(name,defaultParse
}
};
/*
Compose a string comprising the attributes and variables to identify this transclusion for recursion detection
*/
TranscludeWidget.prototype.makeRecursionMarker = function() {
var marker = {
attributes: {},
variables: {}
}
$tw.utils.each(this.attributes,function(value,name) {
marker.attributes[name] = value;
});
for(var name in this.variables) {
if(name !== "$transclusion") {
marker.variables[name] = this.getVariable(name);
}
};
return JSON.stringify(marker);
};
/*
Compose a string comprising the title, field and/or index to identify this transclusion for recursion detection
*/
TranscludeWidget.prototype.makeLegacyRecursionMarker = function() {
TranscludeWidget.prototype.makeRecursionMarker = function() {
var output = [];
output.push("{");
output.push(this.getVariable("currentTiddler",{defaultValue: ""}));