diff --git a/core/modules/widgets/importvariables.js b/core/modules/widgets/importvariables.js index e720dc07b..3ea1d1174 100644 --- a/core/modules/widgets/importvariables.js +++ b/core/modules/widgets/importvariables.js @@ -61,7 +61,14 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { var widget = widgetPointer.makeChildWidget(node); widget.computeAttributes(); widget.execute(); - $tw.utils.extend(widgetPointer.variables,widget.variables); + // We SHALLOW copy over all variables + // in widget. We can't use + // $tw.utils.assign, because that copies + // up the prototype chain, which we + // don't want. + $tw.utils.each(Object.keys(widget.variables), function(key) { + widgetPointer.variables[key] = widget.variables[key]; + }); } else { widgetPointer.makeChildWidgets([node]); widgetPointer = widgetPointer.children[0]; diff --git a/editions/test/tiddlers/tests/test-widget.js b/editions/test/tiddlers/tests/test-widget.js index 5983b97dd..c20305746 100755 --- a/editions/test/tiddlers/tests/test-widget.js +++ b/editions/test/tiddlers/tests/test-widget.js @@ -517,6 +517,38 @@ describe("Widget module", function() { // Test the rendering expect(wrapper.innerHTML).toBe("

Don't forget me.

"); }); + + /** This test reproduces issue #4504. + * + * The importvariable widget was creating redundant copies into + * itself of variables in widgets higher up in the tree. Normally, + * this caused no errors, but it would mess up qualify-macros. + * They would find multiple instances of the same transclusion + * variable if a transclusion occured higher up in the widget tree + * than an importvariables AND that importvariables was importing + * at least ONE variable. + */ + it("adding imported variables doesn't change qualifyers", function() { + var wiki = new $tw.Wiki(); + function wikiparse(text) { + var tree = parseText(text,wiki); + var widgetNode = createWidgetNode(tree,wiki); + var wrapper = renderWidgetNode(widgetNode); + return wrapper.innerHTML; + }; + wiki.addTiddlers([ + {title: "body", text: "\\import A\n<>"}, + {title: "A", text: "\\define unused() ignored"} + ]); + // This transclude wraps "body", which has an + // importvariable widget in it. + var withA = wikiparse("{{body}}"); + wiki.addTiddler({title: "A", text: ""}); + var withoutA = wikiparse("{{body}}"); + // Importing two different version of "A" shouldn't cause + // the <> widget to spit out something different. + expect(withA).toBe(withoutA); + }); }); })();