Introduced preliminary idea for infinite recurse exception
This commit is contained in:
parent
4e06c31022
commit
bc89805368
|
@ -0,0 +1,17 @@
|
|||
/*\
|
||||
title: $:/core/modules/utils/errors.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Custom errors for TiddlyWiki.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
function TranscludeRecursionError(transcludeMarker) {
|
||||
this.marker = transcludeMarker;
|
||||
};
|
||||
|
||||
exports.TranscludeRecursionError = TranscludeRecursionError;
|
||||
|
||||
})();
|
|
@ -30,7 +30,24 @@ TranscludeWidget.prototype.render = function(parent,nextSibling) {
|
|||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
try {
|
||||
this.renderChildren(parent,nextSibling);
|
||||
} catch(error) {
|
||||
if(error instanceof $tw.utils.TranscludeRecursionError) {
|
||||
// We were infinite looping.
|
||||
// We need to try and abort as much of the loop as we can, so we will keep "throwing" upward until we find a transclusion that has a different signature.
|
||||
// Hopefully that will land us just outside where the loop began. That's where we want to issue an error.
|
||||
// Rendering widgets beneath this point may result in a freezing browser if they explode exponentially.
|
||||
if(error.marker !== this.getVariable("transclusion")) {
|
||||
this.children = [this.makeChildWidget({type: "error", attributes: {
|
||||
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
|
||||
}})];
|
||||
this.renderChildren(parent,nextSibling);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -495,9 +495,7 @@ Widget.prototype.makeChildWidgets = function(parseTreeNodes,options) {
|
|||
var self = this;
|
||||
// Check for too much recursion
|
||||
if(this.getAncestorCount() > MAX_WIDGET_TREE_DEPTH) {
|
||||
this.children.push(this.makeChildWidget({type: "error", attributes: {
|
||||
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
|
||||
}}));
|
||||
throw new $tw.utils.TranscludeRecursionError(this.getVariable("transclusion"));
|
||||
} else {
|
||||
// Create set variable widgets for each variable
|
||||
$tw.utils.each(options.variables,function(value,name) {
|
||||
|
|
|
@ -160,6 +160,26 @@ describe("Widget module", function() {
|
|||
expect(wrapper.innerHTML).toBe("<span class=\"tc-error\">Recursive transclusion error in transclude widget</span>");
|
||||
});
|
||||
|
||||
it("should handle recursion with branching nodes", function() {
|
||||
var wiki = new $tw.Wiki();
|
||||
// Add a tiddler
|
||||
wiki.addTiddlers([
|
||||
{title: "TiddlerOne", text: "<$tiddler tiddler='TiddlerOne'><$transclude /> <$transclude /></$tiddler>"},
|
||||
]);
|
||||
// Test parse tree
|
||||
var parseTreeNode = {type: "widget", children: [
|
||||
{type: "transclude", attributes: {
|
||||
"tiddler": {type: "string", value: "TiddlerOne"}
|
||||
}}
|
||||
]};
|
||||
// Construct the widget node
|
||||
var widgetNode = createWidgetNode(parseTreeNode,wiki);
|
||||
// Render the widget node to the DOM
|
||||
var wrapper = renderWidgetNode(widgetNode);
|
||||
// Test the rendering
|
||||
expect(wrapper.innerHTML).toBe("<span class=\"tc-error\">Recursive transclusion error in transclude widget</span> <span class=\"tc-error\">Recursive transclusion error in transclude widget</span>");
|
||||
});
|
||||
|
||||
it("should deal with SVG elements", function() {
|
||||
var wiki = new $tw.Wiki();
|
||||
// Construct the widget node
|
||||
|
|
Loading…
Reference in New Issue