From 42841c41a49bf9dc0c9c2eebefd54f35b38d9544 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Wed, 30 Jan 2019 22:21:44 +0100 Subject: [PATCH 01/16] fix: disallow access to the constructor in templates to prevent RCE This commit fixes a Remote Code Execution (RCE) reported by npm-security. Access to non-enumerable "constructor"-properties is now prohibited by the compiled template-code, because this the first step on the way to creating and execution arbitrary JavaScript code. The vulnerability affects systems where an attacker is allowed to inject templates into the Handlebars setup. Further details of the attack may be disclosed by npm-security. Closes #1267 Closes #1495 --- .../compiler/javascript-compiler.js | 3 +++ spec/security.js | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 spec/security.js diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 471144dd3..ff98ad9e4 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -13,6 +13,9 @@ JavaScriptCompiler.prototype = { // PUBLIC API: You can override these methods in a subclass to provide // alternative compiled forms for name lookup and buffering semantics nameLookup: function(parent, name/* , type*/) { + if (name === 'constructor') { + return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')']; + } if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { return [parent, '.', name]; } else { diff --git a/spec/security.js b/spec/security.js new file mode 100644 index 000000000..45b96c34b --- /dev/null +++ b/spec/security.js @@ -0,0 +1,23 @@ +describe('security issues', function() { + describe('GH-1495: Prevent Remote Code Execution via constructor', function() { + it('should not allow constructors to be accessed', function() { + shouldCompileTo('{{constructor.name}}', {}, ''); + }); + + it('should allow the "constructor" property to be accessed if it is enumerable', function() { + shouldCompileTo('{{constructor.name}}', {'constructor': { + 'name': 'here we go' + }}, 'here we go'); + }); + + it('should allow prototype properties that are not constructors', function() { + class TestClass { + get abc() { + return 'xyz'; + } + } + shouldCompileTo('{{#with this as |obj|}}{{obj.abc}}{{/with}}', + new TestClass(), 'xyz'); + }); + }); +}); From c6a8fc1c045b6b7d6fdb94a32b991b2803bff205 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Thu, 7 Feb 2019 08:42:04 +0100 Subject: [PATCH 02/16] chore: add .idea and yarn-error.log to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3c6d099f1..42b64dde0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ node_modules *.sublime-workspace npm-debug.log sauce_connect.log* +.idea +yarn-error.log From dbc50ac7050f030743bc9a1186c1eea521fe1fff Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Thu, 7 Feb 2019 09:53:09 +0100 Subject: [PATCH 03/16] chore: bump version of grunt-saucelabs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f18bcffe..379eb2737 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "grunt-contrib-uglify": "^1", "grunt-contrib-watch": "^1.1.0", "grunt-eslint": "^20.1.0", - "grunt-saucelabs": "8.x", + "grunt-saucelabs": "9.x", "grunt-webpack": "^1.0.8", "istanbul": "^0.3.0", "jison": "~0.3.0", From f1c8b2e2a2837e77f188e4e6cbadaae0749d5628 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Thu, 7 Feb 2019 10:04:17 +0100 Subject: [PATCH 04/16] chore: disable sauce-labs Related to #1497 --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index ce85e9a4a..7542a7ffc 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -228,7 +228,7 @@ module.exports = function(grunt) { grunt.task.loadTasks('tasks'); grunt.registerTask('bench', ['metrics']); - grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []); + grunt.registerTask('sauce', [] /* process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : [] */); grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']); From b02e9a25eea6a8829e5b794f5506d7806d48c73b Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Thu, 7 Feb 2019 10:14:44 +0100 Subject: [PATCH 05/16] test: run appveyor tests in Node 10 --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b67fb4ca5..563aaf93c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,7 @@ # Test against these versions of Node.js environment: matrix: - - nodejs_version: "4" - - nodejs_version: "5" + - nodejs_version: "10" platform: - x64 From b92589a3b0b6e9f29413b1ec0fdaf715c35ef71f Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sun, 17 Feb 2019 22:03:15 +0100 Subject: [PATCH 06/16] test: add test for NodeJS compatibility The test is a simple addition to the existing tests. It should ensure that the built Handlebars artifact only uses language features that are available in old versions of NodeJS. A simple program and the precompiler are started with NodeJS 0.10 to 11 --- .travis.yml | 1 + Gruntfile.js | 3 +- multi-nodejs-test/.eslintrc.js | 114 ++++++++++++++++++++++++++++ multi-nodejs-test/expected.txt | 1 + multi-nodejs-test/run-handlebars.js | 13 ++++ multi-nodejs-test/run-tests.sh | 21 +++++ multi-nodejs-test/template.txt.hbs | 1 + 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 multi-nodejs-test/.eslintrc.js create mode 100644 multi-nodejs-test/expected.txt create mode 100755 multi-nodejs-test/run-handlebars.js create mode 100755 multi-nodejs-test/run-tests.sh create mode 100644 multi-nodejs-test/template.txt.hbs diff --git a/.travis.yml b/.travis.yml index ce9690a9c..b8c200dd2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ before_install: - npm install -g grunt-cli script: - grunt --stack travis +- multi-nodejs-test/run-tests.sh 0.10 0.12 4 5 6 7 8 9 10 11 email: on_failure: change on_success: never diff --git a/Gruntfile.js b/Gruntfile.js index 7542a7ffc..ff89c737d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,7 +12,8 @@ module.exports = function(grunt) { 'bench/**/*.js', 'tasks/**/*.js', 'lib/**/!(*.min|parser).js', - 'spec/**/!(*.amd|json2|require).js' + 'spec/**/!(*.amd|json2|require).js', + 'multi-nodejs-test/*.js' ] }, diff --git a/multi-nodejs-test/.eslintrc.js b/multi-nodejs-test/.eslintrc.js new file mode 100644 index 000000000..6d3592c7b --- /dev/null +++ b/multi-nodejs-test/.eslintrc.js @@ -0,0 +1,114 @@ +module.exports = { + "extends": "eslint:recommended", + "globals": { + "self": false + }, + "env": { + "node": true + }, + "rules": { + // overrides eslint:recommended defaults + "no-sparse-arrays": "off", + "no-func-assign": "off", + "no-console": "off", + "no-debugger": "warn", + "no-unreachable": "warn", + + // Possible Errors // + //-----------------// + "no-unsafe-negation": "error", + + + // Best Practices // + //----------------// + "curly": "error", + "default-case": "warn", + "dot-notation": ["error", { "allowKeywords": false }], + "guard-for-in": "warn", + "no-alert": "error", + "no-caller": "error", + "no-div-regex": "warn", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-floating-decimal": "error", + "no-implied-eval": "error", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-multi-spaces": "error", + "no-multi-str": "warn", + "no-global-assign": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-process-env": "error", + "no-proto": "error", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-unused-expressions": "error", + "no-warning-comments": "warn", + "no-with": "error", + "radix": "error", + "wrap-iife": "error", + + + // Variables // + //-----------// + "no-catch-shadow": "error", + "no-label-var": "error", + "no-shadow-restricted-names": "error", + "no-undef-init": "error", + "no-use-before-define": ["error", "nofunc"], + + + // Stylistic Issues // + //------------------// + "comma-dangle": ["error", "never"], + "quote-props": ["error", "as-needed", { "keywords": true, "unnecessary": false }], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "camelcase": "error", + "comma-spacing": ["error", { "before": false, "after": true }], + "comma-style": ["error", "last"], + "consistent-this": ["warn", "self"], + "eol-last": "error", + "func-style": ["error", "declaration"], + "key-spacing": ["error", { + "beforeColon": false, + "afterColon": true + }], + "new-cap": "error", + "new-parens": "error", + "no-array-constructor": "error", + "no-lonely-if": "error", + "no-mixed-spaces-and-tabs": "error", + "no-nested-ternary": "warn", + "no-new-object": "error", + "no-spaced-func": "error", + "no-trailing-spaces": "error", + "no-extra-parens": ["error", "functions"], + "quotes": ["error", "single", "avoid-escape"], + "semi": "error", + "semi-spacing": ["error", { "before": false, "after": true }], + "keyword-spacing": "error", + "space-before-blocks": ["error", "always"], + "space-before-function-paren": ["error", { "anonymous": "never", "named": "never" }], + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": ["error", "always", { "markers": [","] }], + "wrap-regex": "warn", + + // ECMAScript 6 // + //--------------// + "no-var": "off" + }, + "parserOptions": { + "sourceType": "module" + } +} \ No newline at end of file diff --git a/multi-nodejs-test/expected.txt b/multi-nodejs-test/expected.txt new file mode 100644 index 000000000..19a4be2d7 --- /dev/null +++ b/multi-nodejs-test/expected.txt @@ -0,0 +1 @@ +Author: Yehuda diff --git a/multi-nodejs-test/run-handlebars.js b/multi-nodejs-test/run-handlebars.js new file mode 100755 index 000000000..58bc8d495 --- /dev/null +++ b/multi-nodejs-test/run-handlebars.js @@ -0,0 +1,13 @@ +// This test should run with node 0.10 as long as Handlebars has been compiled before +var Handlebars = require('../'); +var fs = require('fs'); + +console.log('Testing build Handlebars with Node version ' + process.version); +var template = fs.readFileSync(require.resolve('./template.txt.hbs'), 'utf-8'); +var compiledOutput = Handlebars.compile(template)({author: 'Yehuda'}).trim(); +var expectedOutput = fs.readFileSync(require.resolve('./expected.txt'), 'utf-8').trim(); + +if (compiledOutput !== expectedOutput) { + throw new Error('Compiled output (' + compiledOutput + ') did not match expected output (' + expectedOutput + ')'); +} +console.log('Success'); diff --git a/multi-nodejs-test/run-tests.sh b/multi-nodejs-test/run-tests.sh new file mode 100755 index 000000000..174a12ccb --- /dev/null +++ b/multi-nodejs-test/run-tests.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +cd "$( dirname "$( readlink -f "$0" )" )" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + +# This script tests with precompiler and the built distribution with multiple NodeJS version. +# The rest of the travis-build will only work with newer NodeJS versions, because the build +# tools don't support older versions. +# However, the built distribution should work with older NodeJS versions as well. +# This test is simple by design. It merely ensures, that calling Handlebars does not fail with old versions. +# It does (almost) not test for correctness, because that is already done in the mocha-tests. +# And it does not use any NodeJS based testing framwork to make this part independent of the Node version. + +# A list of NodeJS versions is expected as cli-args +echo "Handlebars should be able to run in various versions of NodeJS" +for i in "$@" ; do + nvm install "$i" + nvm exec "$i" node ./run-handlebars.js >/dev/null || exit 1 + nvm exec "$i" node ../bin/handlebars template.txt.hbs >/dev/null || exit 1 + echo Success +done \ No newline at end of file diff --git a/multi-nodejs-test/template.txt.hbs b/multi-nodejs-test/template.txt.hbs new file mode 100644 index 000000000..61d4dd7fa --- /dev/null +++ b/multi-nodejs-test/template.txt.hbs @@ -0,0 +1 @@ +Author: {{author}} From 048f2ce7d21c556fc7253ff014079597219c01fd Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 16 Feb 2019 22:15:37 +0100 Subject: [PATCH 07/16] refactor: replace "async" with "neo-async" The main reason is that neo-async takes a lot less space due to the missing lodash-dependency. The other is speed. closes #1431 --- bench/dist-size.js | 2 +- lib/precompiler.js | 2 +- package.json | 2 +- tasks/metrics.js | 2 +- tasks/publish.js | 4 ++-- tasks/version.js | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bench/dist-size.js b/bench/dist-size.js index 9176054d5..d0bd24892 100644 --- a/bench/dist-size.js +++ b/bench/dist-size.js @@ -1,4 +1,4 @@ -var async = require('async'), +var async = require('neo-async'), fs = require('fs'), zlib = require('zlib'); diff --git a/lib/precompiler.js b/lib/precompiler.js index ab3eb201d..ecf264eff 100644 --- a/lib/precompiler.js +++ b/lib/precompiler.js @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -import Async from 'async'; +import Async from 'neo-async'; import fs from 'fs'; import * as Handlebars from './handlebars'; import {basename} from 'path'; diff --git a/package.json b/package.json index de4efbf87..87b4e8423 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "node": ">=0.4.7" }, "dependencies": { - "async": "^2.5.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", "source-map": "^0.6.1" }, diff --git a/tasks/metrics.js b/tasks/metrics.js index b04967dd0..a1fa5c95a 100644 --- a/tasks/metrics.js +++ b/tasks/metrics.js @@ -1,5 +1,5 @@ var _ = require('underscore'), - async = require('async'), + async = require('neo-async'), metrics = require('../bench'); module.exports = function(grunt) { diff --git a/tasks/publish.js b/tasks/publish.js index 38039c6d4..c3729596b 100644 --- a/tasks/publish.js +++ b/tasks/publish.js @@ -1,5 +1,5 @@ var _ = require('underscore'), - async = require('async'), + async = require('neo-async'), AWS = require('aws-sdk'), git = require('./util/git'), semver = require('semver'); @@ -66,7 +66,7 @@ module.exports = function(grunt) { var s3 = new AWS.S3(), bucket = process.env.S3_BUCKET_NAME; - async.forEach(_.keys(files), function(file, callback) { + async.each(_.keys(files), function(file, callback) { var params = {Bucket: bucket, Key: file, Body: grunt.file.read(files[file])}; s3.putObject(params, function(err) { if (err) { diff --git a/tasks/version.js b/tasks/version.js index 3fe3efab1..05f703419 100644 --- a/tasks/version.js +++ b/tasks/version.js @@ -1,4 +1,4 @@ -var async = require('async'), +var async = require('neo-async'), git = require('./util/git'), semver = require('semver'); From b2e2cfe56d844a351e763bba8b04c2571bba3380 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Tue, 19 Feb 2019 10:31:42 +0100 Subject: [PATCH 08/16] chore: re-activate saucelabs --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index ff89c737d..838e7b395 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -229,7 +229,7 @@ module.exports = function(grunt) { grunt.task.loadTasks('tasks'); grunt.registerTask('bench', ['metrics']); - grunt.registerTask('sauce', [] /* process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : [] */); + grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []); grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']); From 40fb115e537e49f0fc8c95aa529cacfa0ff7cbe9 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Tue, 19 Feb 2019 10:49:24 +0100 Subject: [PATCH 09/16] Revert "chore: re-activate saucelabs" This reverts commit b2e2cfe56d844a351e763bba8b04c2571bba3380. --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 838e7b395..ff89c737d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -229,7 +229,7 @@ module.exports = function(grunt) { grunt.task.loadTasks('tasks'); grunt.registerTask('bench', ['metrics']); - grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []); + grunt.registerTask('sauce', [] /* process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : [] */); grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']); From 5cedd62d7b6da77fb6b86fe7e2579ce27100a560 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Fri, 22 Feb 2019 00:30:51 +0100 Subject: [PATCH 10/16] fix: add "runtime.d.ts" to allow "require('handlebars/runtime')" see #1499 --- runtime.d.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 runtime.d.ts diff --git a/runtime.d.ts b/runtime.d.ts new file mode 100644 index 000000000..0d5105eb7 --- /dev/null +++ b/runtime.d.ts @@ -0,0 +1,5 @@ +import Handlebars = require('handlebars') + +declare module "handlebars/runtime" { + +} \ No newline at end of file From 445ae12fa473ec5b0d54483b679736ed70bab5a3 Mon Sep 17 00:00:00 2001 From: Qiang Li Date: Tue, 26 Feb 2019 00:18:18 -0800 Subject: [PATCH 11/16] deprecate substr method and use existing strip function in grammar --- lib/handlebars/compiler/helpers.js | 2 +- src/handlebars.l | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js index 432df877c..f26b4e15c 100644 --- a/lib/handlebars/compiler/helpers.js +++ b/lib/handlebars/compiler/helpers.js @@ -24,7 +24,7 @@ export function SourceLocation(source, locInfo) { export function id(token) { if (/^\[.*\]$/.test(token)) { - return token.substr(1, token.length - 2); + return token.substring(1, token.length - 1); } else { return token; } diff --git a/src/handlebars.l b/src/handlebars.l index e9de1029b..90acffec0 100644 --- a/src/handlebars.l +++ b/src/handlebars.l @@ -4,7 +4,7 @@ %{ function strip(start, end) { - return yytext = yytext.substr(start, yyleng-end); + return yytext = yytext.substring(start, yyleng - end + start); } %} @@ -59,7 +59,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} if (this.conditionStack[this.conditionStack.length-1] === 'raw') { return 'CONTENT'; } else { - yytext = yytext.substr(5, yyleng-9); + strip(5, 9); return 'END_RAW_BLOCK'; } } From 7840ab66a5cf754e2325ce269c0134ad8aff5b6b Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Fri, 15 Mar 2019 22:39:36 +0100 Subject: [PATCH 12/16] test: make security testcase internet explorer compatible Internet Explorer does not support the 'class Testclass {}' notation, and tests are not compiled using babel. closes #1497 --- spec/security.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/spec/security.js b/spec/security.js index 45b96c34b..12b96e629 100644 --- a/spec/security.js +++ b/spec/security.js @@ -11,11 +11,16 @@ describe('security issues', function() { }); it('should allow prototype properties that are not constructors', function() { - class TestClass { - get abc() { + function TestClass() { + } + + Object.defineProperty(TestClass.prototype, 'abc', { + get: function() { return 'xyz'; } - } + + }); + shouldCompileTo('{{#with this as |obj|}}{{obj.abc}}{{/with}}', new TestClass(), 'xyz'); }); From 684f1032c62758d1cb548d4ff9e7582a6554d313 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Fri, 15 Mar 2019 22:49:36 +0100 Subject: [PATCH 13/16] chore: reactivate saucelabs-tests --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index ff89c737d..838e7b395 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -229,7 +229,7 @@ module.exports = function(grunt) { grunt.task.loadTasks('tasks'); grunt.registerTask('bench', ['metrics']); - grunt.registerTask('sauce', [] /* process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : [] */); + grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []); grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']); From e5c39375ac423bf752cd1c5b99affce23b528c4d Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 16 Mar 2019 22:24:34 +0100 Subject: [PATCH 14/16] Update release notes --- release-notes.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index 5b54c5e73..15ac15539 100644 --- a/release-notes.md +++ b/release-notes.md @@ -2,7 +2,21 @@ ## Development -[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...master) +[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.1...master) + +## v4.1.1 - March 16th, 2019 +Bugfixes: +- fix: add "runtime.d.ts" to allow "require('handlebars/runtime')" in TypeScript - 5cedd62 + +Refactorings: +- replace "async" with "neo-async" - 048f2ce +- use "substring"-function instead of "substr" - 445ae12 + +Compatibility notes: +- This is a bugfix release. There are no breaking change and no new features. + + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...v4.1.1) ## v4.1.0 - February 7th, 2019 New Features From 25b2e11dd9b40f0d4437855174bfab184edfb4cc Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 16 Mar 2019 22:28:03 +0100 Subject: [PATCH 15/16] Update release notes --- release-notes.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/release-notes.md b/release-notes.md index 15ac15539..10b6455de 100644 --- a/release-notes.md +++ b/release-notes.md @@ -16,6 +16,20 @@ Compatibility notes: - This is a bugfix release. There are no breaking change and no new features. +[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.1...v4.1.1) + +## v4.1.1 - March 16th, 2019 +Bugfixes: +- fix: add "runtime.d.ts" to allow "require('handlebars/runtime')" in TypeScript - 5cedd62 + +Refactorings: +- replace "async" with "neo-async" - 048f2ce +- use "substring"-function instead of "substr" - 445ae12 + +Compatibility notes: +- This is a bugfix release. There are no breaking change and no new features. + + [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...v4.1.1) ## v4.1.0 - February 7th, 2019 From f691db546e7563e1db3437d5a72f478f9e556714 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 16 Mar 2019 22:28:38 +0100 Subject: [PATCH 16/16] v4.1.1 --- components/bower.json | 2 +- components/handlebars.js.nuspec | 2 +- components/package.json | 2 +- lib/handlebars/base.js | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/bower.json b/components/bower.json index af87b72af..ffd98e358 100644 --- a/components/bower.json +++ b/components/bower.json @@ -1,6 +1,6 @@ { "name": "handlebars", - "version": "4.1.0", + "version": "4.1.1", "main": "handlebars.js", "license": "MIT", "dependencies": {} diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec index a4740212a..e6a38c6f2 100644 --- a/components/handlebars.js.nuspec +++ b/components/handlebars.js.nuspec @@ -2,7 +2,7 @@ handlebars.js - 4.1.0 + 4.1.1 handlebars.js Authors https://github.com/wycats/handlebars.js/blob/master/LICENSE https://github.com/wycats/handlebars.js/ diff --git a/components/package.json b/components/package.json index 7013be4a4..ced91e119 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "handlebars", - "version": "4.1.0", + "version": "4.1.1", "license": "MIT", "jspm": { "main": "handlebars", diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index 22307b9da..a1278d1e5 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -4,7 +4,7 @@ import {registerDefaultHelpers} from './helpers'; import {registerDefaultDecorators} from './decorators'; import logger from './logger'; -export const VERSION = '4.1.0'; +export const VERSION = '4.1.1'; export const COMPILER_REVISION = 7; export const REVISION_CHANGES = { diff --git a/package.json b/package.json index 87b4e8423..edf11b7c2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "handlebars", "barename": "handlebars", - "version": "4.1.0", + "version": "4.1.1", "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration", "homepage": "http://www.handlebarsjs.com/", "keywords": [