Repository: mozilla/nunjucks (js)

Issue:
`{{ arr | safe }}` should not escape
`render('{{ arr | safe }}', { arr: [ '<html>' ] })` => `&lt;html&gt;`

https://github.com/mozilla/nunjucks/blob/master/src/runtime.js#L190

@vecmezoni is this a bug or user should use `{{ arr | join | safe }}` ?

Pull request description:
fix: safe should call toString
close #847

relate: https://github.com/mozilla/nunjucks/pull/843#discussion-diff-78676929

Patch:
diff --git a/src/filters.js b/src/filters.js
index 0465b61..d8fc12e 100644
--- a/src/filters.js
+++ b/src/filters.js
@@ -124,8 +124,11 @@ var filters = {
     },
 
     safe: function(str) {
+        if (str instanceof r.SafeString) {
+            return str;
+        }
         str = (str === null || str === undefined) ? '' : str;
-        return r.markSafe(str);
+        return r.markSafe(str.toString());
     },
 
     first: function(arr) {


Test patch:
diff --git a/tests/compiler.js b/tests/compiler.js
index 05b9271..7079ec4 100644
--- a/tests/compiler.js
+++ b/tests/compiler.js
@@ -1313,20 +1313,28 @@
                 expect(res).to.be('');
             });
 
-            render('{{ foo | safe }}', { foo: null }, { autoescape: true }, function (err, res) {
-                expect(res).to.be('');
+            render('{{ foo }}', { foo: ['<p>foo</p>']}, { autoescape: true }, function(err, res) {
+                expect(res).to.be('&lt;p&gt;foo&lt;/p&gt;');
             });
 
-            render('{{ foo }}', { foo: ['<p>foo</p>']}, { autoescape: true }, function(err, res) {
+            render('{{ foo }}', { foo: { toString: function () { return '<p>foo</p>' } } }, { autoescape: true }, function (err, res) {
                 expect(res).to.be('&lt;p&gt;foo&lt;/p&gt;');
             });
 
+            render('{{ foo | safe }}', { foo: null }, { autoescape: true }, function (err, res) {
+                expect(res).to.be('');
+            });
+
             render('{{ foo | safe }}', { foo: '<p>foo</p>' }, { autoescape: true }, function (err, res) {
                 expect(res).to.be('<p>foo</p>');
             });
 
-            render('{{ foo }}', { foo: {toString: function() {return '<p>foo</p>'}}}, { autoescape: true }, function(err, res) {
-                expect(res).to.be('&lt;p&gt;foo&lt;/p&gt;');
+            render('{{ foo | safe }}', { foo: ['<p>foo</p>'] }, { autoescape: true }, function (err, res) {
+                expect(res).to.be('<p>foo</p>');
+            });
+
+            render('{{ foo | safe }}', { foo: { toString: function () { return '<p>foo</p>' } } }, { autoescape: true }, function (err, res) {
+                expect(res).to.be('<p>foo</p>');
             });
 
             finish(done);