diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 6e7a0c12c..ef3fa71a5 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -426,7 +426,10 @@ JavaScriptCompiler.prototype = { // Otherwise, the empty string is appended append: function () { if (this.isInline()) { - this.replaceStack((current) => [' != null ? ', current, ' : ""']); + // Coerce non-null values to a String so that adjacent buffer appends are + // concatenated rather than combined by the merge `+` (e.g. numeric values + // such as `{{a}}{{b}}` with `noEscape` must yield "12", not 3). + this.replaceStack((current) => [' != null ? "" + ', current, ' : ""']); this.pushSource(this.appendToBuffer(this.popStack())); } else { diff --git a/spec/basic.js b/spec/basic.js index f3d37e250..9809148d3 100644 --- a/spec/basic.js +++ b/spec/basic.js @@ -111,6 +111,22 @@ describe('basic context', function () { .toCompileTo('num: 0'); }); + it('does not add adjacent numeric values with noEscape or raw mustaches', function () { + expectTemplate('{{a}}{{b}}') + .withCompileOptions({ noEscape: true }) + .withInput({ a: 1, b: 2 }) + .toCompileTo('12'); + + expectTemplate('{{a}}{{b}}{{c}}') + .withCompileOptions({ noEscape: true }) + .withInput({ a: 1, b: 2, c: 3 }) + .toCompileTo('123'); + + expectTemplate('{{{a}}}{{{b}}}') + .withInput({ a: 1, b: 2 }) + .toCompileTo('12'); + }); + it('false', function () { /* eslint-disable no-new-wrappers */ expectTemplate('val1: {{val1}}, val2: {{val2}}')