From c02b05fa819f46bb66c878bebc6e8006408ebd5c Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 10 Nov 2019 16:34:38 +0100
Subject: [PATCH 1/9] fix: use !== 0 instead of != 0

---
 tasks/test.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tasks/test.js b/tasks/test.js
index 6bee3920a..a17fc2a22 100644
--- a/tasks/test.js
+++ b/tasks/test.js
@@ -33,7 +33,7 @@ module.exports = function(grunt) {
 
     var runner = childProcess.fork('./spec/env/runner', [], {stdio: 'inherit'});
     runner.on('close', function(code) {
-      if (code != 0) {
+      if (code !== 0) {
         grunt.fatal(code + ' tests failed');
       }
       done();
@@ -55,7 +55,7 @@ module.exports = function(grunt) {
 
     var runner = childProcess.fork('./spec/env/runner', ['--min'], {stdio: 'inherit'});
     runner.on('close', function(code) {
-      if (code != 0) {
+      if (code !== 0) {
         grunt.fatal(code + ' tests failed');
       }
       done();

From 93e284ed9be1e38c5e6945f15af1ccd689f2ada6 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 10 Nov 2019 16:00:43 +0100
Subject: [PATCH 2/9] chore: add chai and dirty-chai for better test assertions

---
 package-lock.json | 61 ++++++++++++++++++++++++++++++++++++++++++++++-
 package.json      |  2 ++
 spec/env/node.js  |  6 +++++
 spec/index.html   |  2 ++
 4 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/package-lock.json b/package-lock.json
index 332d8fb1b..eb7b05bd1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.0",
+  "version": "4.5.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -324,6 +324,12 @@
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
       "dev": true
     },
+    "assertion-error": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+      "dev": true
+    },
     "assign-symbols": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -985,6 +991,20 @@
         "lazy-cache": "^1.0.3"
       }
     },
+    "chai": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
+      "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
+      "dev": true,
+      "requires": {
+        "assertion-error": "^1.1.0",
+        "check-error": "^1.0.2",
+        "deep-eql": "^3.0.1",
+        "get-func-name": "^2.0.0",
+        "pathval": "^1.1.0",
+        "type-detect": "^4.0.5"
+      }
+    },
     "chalk": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -1004,6 +1024,12 @@
       "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
       "dev": true
     },
+    "check-error": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+      "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+      "dev": true
+    },
     "chokidar": {
       "version": "1.5.2",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.5.2.tgz",
@@ -1467,6 +1493,15 @@
       "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
       "dev": true
     },
+    "deep-eql": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+      "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+      "dev": true,
+      "requires": {
+        "type-detect": "^4.0.0"
+      }
+    },
     "deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -1619,6 +1654,12 @@
       "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=",
       "dev": true
     },
+    "dirty-chai": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/dirty-chai/-/dirty-chai-2.0.1.tgz",
+      "integrity": "sha512-ys79pWKvDMowIDEPC6Fig8d5THiC0DJ2gmTeGzVAoEH18J8OzLud0Jh7I9IWg3NSk8x2UocznUuFmfHCXYZx9w==",
+      "dev": true
+    },
     "doctrine": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -3287,6 +3328,12 @@
       "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=",
       "dev": true
     },
+    "get-func-name": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+      "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+      "dev": true
+    },
     "get-stdin": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
@@ -6234,6 +6281,12 @@
         "pinkie-promise": "^2.0.0"
       }
     },
+    "pathval": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+      "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+      "dev": true
+    },
     "pbkdf2-compat": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz",
@@ -8162,6 +8215,12 @@
         "prelude-ls": "~1.1.2"
       }
     },
+    "type-detect": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+      "dev": true
+    },
     "type-is": {
       "version": "1.6.16",
       "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
diff --git a/package.json b/package.json
index d753c9b2a..fdac39237 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,8 @@
     "babel-loader": "^5.0.0",
     "babel-runtime": "^5.1.10",
     "benchmark": "~1.0",
+    "chai": "^4.2.0",
+    "dirty-chai": "^2.0.1",
     "dtslint": "^0.5.5",
     "dustjs-linkedin": "^2.0.2",
     "eco": "~1.1.0-rc-3",
diff --git a/spec/env/node.js b/spec/env/node.js
index 881609d2e..8b97c4d53 100644
--- a/spec/env/node.js
+++ b/spec/env/node.js
@@ -1,5 +1,11 @@
 require('./common');
 
+var chai = require('chai');
+var dirtyChai = require('dirty-chai');
+
+chai.use(dirtyChai);
+global.expect = chai.expect;
+
 global.Handlebars = require('../../lib');
 
 global.CompilerContext = {
diff --git a/spec/index.html b/spec/index.html
index 5db2146ad..3528b78d6 100644
--- a/spec/index.html
+++ b/spec/index.html
@@ -20,6 +20,8 @@
       }
     </script>
     <script src="/node_modules/mocha/mocha.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+    <script src="/node_modules/dirty-chai/lib/dirty-chai.js"></script>
     <script>
       mocha.setup('bdd');
     </script>

From 93516a0b07026ebd23c84fddf270a0c8b570bc59 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Thu, 14 Nov 2019 08:28:15 +0100
Subject: [PATCH 3/9] test: add sinon.js for spies, deprecate current
 assertions

- the goal is to get overall cleaner test.
- chai and sinon are standard libraries for testing
  assertions and spies. We should not use custom ones.
---
 package-lock.json     | 120 +++++++++++++++++++++++++++++++++++++++++-
 package.json          |   1 +
 spec/.eslintrc        |   9 ++--
 spec/amd-runtime.html |   5 +-
 spec/amd.html         |   5 +-
 spec/env/browser.js   |   9 ++++
 spec/env/common.js    |   8 +++
 spec/env/node.js      |   3 ++
 spec/index.html       |   5 +-
 spec/security.js      |   6 +--
 spec/umd-runtime.html |   5 +-
 spec/umd.html         |   6 ++-
 12 files changed, 169 insertions(+), 13 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index eb7b05bd1..6ed12f6bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.1",
+  "version": "4.5.2",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -83,6 +83,50 @@
         }
       }
     },
+    "@sinonjs/commons": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz",
+      "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==",
+      "dev": true,
+      "requires": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "@sinonjs/formatio": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz",
+      "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==",
+      "dev": true,
+      "requires": {
+        "@sinonjs/commons": "^1",
+        "@sinonjs/samsam": "^3.1.0"
+      }
+    },
+    "@sinonjs/samsam": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz",
+      "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==",
+      "dev": true,
+      "requires": {
+        "@sinonjs/commons": "^1.3.0",
+        "array-from": "^2.1.1",
+        "lodash": "^4.17.15"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
+        }
+      }
+    },
+    "@sinonjs/text-encoding": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz",
+      "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
+      "dev": true
+    },
     "@types/parsimmon": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/@types/parsimmon/-/parsimmon-1.10.0.tgz",
@@ -271,6 +315,12 @@
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
       "dev": true
     },
+    "array-from": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz",
+      "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=",
+      "dev": true
+    },
     "array-slice": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
@@ -4821,6 +4871,12 @@
         "verror": "1.10.0"
       }
     },
+    "just-extend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz",
+      "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==",
+      "dev": true
+    },
     "kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -5255,6 +5311,12 @@
       "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
       "dev": true
     },
+    "lolex": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz",
+      "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==",
+      "dev": true
+    },
     "longest": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -5708,6 +5770,36 @@
       "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=",
       "dev": true
     },
+    "nise": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz",
+      "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==",
+      "dev": true,
+      "requires": {
+        "@sinonjs/formatio": "^3.2.1",
+        "@sinonjs/text-encoding": "^0.7.1",
+        "just-extend": "^4.0.2",
+        "lolex": "^4.1.0",
+        "path-to-regexp": "^1.7.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        },
+        "path-to-regexp": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+          "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+          "dev": true,
+          "requires": {
+            "isarray": "0.0.1"
+          }
+        }
+      }
+    },
     "node-libs-browser": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz",
@@ -7384,6 +7476,32 @@
       "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=",
       "dev": true
     },
+    "sinon": {
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz",
+      "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==",
+      "dev": true,
+      "requires": {
+        "@sinonjs/commons": "^1.4.0",
+        "@sinonjs/formatio": "^3.2.1",
+        "@sinonjs/samsam": "^3.3.3",
+        "diff": "^3.5.0",
+        "lolex": "^4.2.0",
+        "nise": "^1.5.2",
+        "supports-color": "^5.5.0"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
     "slash": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
diff --git a/package.json b/package.json
index fdac39237..426b40cb2 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
     "mock-stdin": "^0.3.0",
     "mustache": "^2.1.3",
     "semver": "^5.0.1",
+    "sinon": "^7.5.0",
     "typescript": "^3.4.3",
     "underscore": "^1.5.1",
     "webpack": "^1.12.6",
diff --git a/spec/.eslintrc b/spec/.eslintrc
index 34319f8c1..8d4ed7a2e 100644
--- a/spec/.eslintrc
+++ b/spec/.eslintrc
@@ -28,15 +28,18 @@
     "stop": true,
     "ok": true,
     "strictEqual": true,
-    "define": true
+    "define": true,
+    "expect": true,
+    "chai": true
   },
   "env": {
     "mocha": true
   },
   "rules": {
     // Disabling for tests, for now.
-    "no-path-concat": 0,
+    "no-path-concat": "off",
 
-    "no-var": 0
+    "no-var": "off",
+    "dot-notation": "off"
   }
 }
\ No newline at end of file
diff --git a/spec/amd-runtime.html b/spec/amd-runtime.html
index 7cc64f190..fc413bd67 100644
--- a/spec/amd-runtime.html
+++ b/spec/amd-runtime.html
@@ -18,11 +18,14 @@
         document.documentElement.className = 'headless';
       }
     </script>
+    <script src="/node_modules/sinon/pkg/sinon.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+    <script src="/node_modules/dirty-chai/lib/dirty-chai.js"></script>
     <script src="/node_modules/mocha/mocha.js"></script>
     <script>
+      window.expect = chai.expect;
       mocha.setup('bdd');
     </script>
-
     <script src="/spec/env/json2.js"></script>
     <script src="/spec/env/require.js"></script>
 
diff --git a/spec/amd.html b/spec/amd.html
index 1149dc706..9ec44e686 100644
--- a/spec/amd.html
+++ b/spec/amd.html
@@ -19,11 +19,14 @@
         document.documentElement.className = 'headless';
       }
     </script>
+    <script src="/node_modules/sinon/pkg/sinon.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+    <script src="/node_modules/dirty-chai/lib/dirty-chai.js"></script>
     <script src="/node_modules/mocha/mocha.js"></script>
     <script>
+      window.expect = chai.expect;
       mocha.setup('bdd');
     </script>
-
     <script src="/spec/env/json2.js"></script>
     <script src="/spec/env/require.js"></script>
 
diff --git a/spec/env/browser.js b/spec/env/browser.js
index 9e54a3977..d1dab0d5e 100644
--- a/spec/env/browser.js
+++ b/spec/env/browser.js
@@ -3,6 +3,15 @@ require('./common');
 var fs = require('fs'),
     vm = require('vm');
 
+var chai = require('chai');
+var dirtyChai = require('dirty-chai');
+
+
+chai.use(dirtyChai);
+global.expect = chai.expect;
+
+global.sinon = require('sinon');
+
 global.Handlebars = 'no-conflict';
 
 var filename = 'dist/handlebars.js';
diff --git a/spec/env/common.js b/spec/env/common.js
index 9523eaeb2..3903e35d4 100644
--- a/spec/env/common.js
+++ b/spec/env/common.js
@@ -63,12 +63,20 @@ global.compileWithPartials = function(string, hashOrArray, partials) {
 };
 
 
+/**
+ * @deprecated Use chai's expect-style API instead (`expect(actualValue).to.equal(expectedValue)`)
+ * @see https://www.chaijs.com/api/bdd/
+ */
 global.equals = global.equal = function equals(a, b, msg) {
   if (a !== b) {
     throw new AssertError("'" + a + "' should === '" + b + "'" + (msg ? ': ' + msg : ''), equals);
   }
 };
 
+/**
+ * @deprecated Use chai's expect-style API instead (`expect(actualValue).to.equal(expectedValue)`)
+ * @see https://www.chaijs.com/api/bdd/#method_throw
+ */
 global.shouldThrow = function(callback, type, msg) {
   var failed;
   try {
diff --git a/spec/env/node.js b/spec/env/node.js
index 8b97c4d53..0695468ba 100644
--- a/spec/env/node.js
+++ b/spec/env/node.js
@@ -3,9 +3,12 @@ require('./common');
 var chai = require('chai');
 var dirtyChai = require('dirty-chai');
 
+
 chai.use(dirtyChai);
 global.expect = chai.expect;
 
+global.sinon = require('sinon');
+
 global.Handlebars = require('../../lib');
 
 global.CompilerContext = {
diff --git a/spec/index.html b/spec/index.html
index 3528b78d6..b768dff76 100644
--- a/spec/index.html
+++ b/spec/index.html
@@ -19,14 +19,15 @@
         document.documentElement.className = 'headless';
       }
     </script>
-    <script src="/node_modules/mocha/mocha.js"></script>
+    <script src="/node_modules/sinon/pkg/sinon.js"></script>
     <script src="/node_modules/chai/chai.js"></script>
     <script src="/node_modules/dirty-chai/lib/dirty-chai.js"></script>
+    <script src="/node_modules/mocha/mocha.js"></script>
     <script>
+      window.expect = chai.expect;
       mocha.setup('bdd');
     </script>
     <script src="/dist/handlebars.js"></script>
-
     <script src="/spec/env/json2.js"></script>
     <script src="/spec/env/common.js"></script>
     <script>
diff --git a/spec/security.js b/spec/security.js
index 80b8e23c2..876b67292 100644
--- a/spec/security.js
+++ b/spec/security.js
@@ -75,11 +75,11 @@ describe('security issues', function() {
             });
             it('should throw an exception when calling  "{{blockHelperMissing "abc" .}}" ', function() {
                 var functionCalls = [];
-                shouldThrow(function() {
+                expect(function() {
                     var template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
                     template({ fn: function() { functionCalls.push('called'); }});
-                }, Error);
-                equals(functionCalls.length, 0);
+                }).to.throw(Error);
+                expect(functionCalls.length).to.equal(0);
             });
             it('should throw an exception when calling  "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function() {
                 shouldThrow(function() {
diff --git a/spec/umd-runtime.html b/spec/umd-runtime.html
index 90b91448a..212d4f2dc 100644
--- a/spec/umd-runtime.html
+++ b/spec/umd-runtime.html
@@ -18,11 +18,14 @@
         document.documentElement.className = 'headless';
       }
     </script>
+    <script src="/node_modules/sinon/pkg/sinon.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+    <script src="/node_modules/dirty-chai/lib/dirty-chai.js"></script>
     <script src="/node_modules/mocha/mocha.js"></script>
     <script>
+      window.expect = chai.expect;
       mocha.setup('bdd');
     </script>
-
     <script src="/spec/env/json2.js"></script>
     <script src="/spec/env/require.js"></script>
 
diff --git a/spec/umd.html b/spec/umd.html
index 5f3863fc8..53d6b2716 100644
--- a/spec/umd.html
+++ b/spec/umd.html
@@ -18,11 +18,15 @@
         document.documentElement.className = 'headless';
       }
     </script>
+
+    <script src="/node_modules/sinon/pkg/sinon.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+    <script src="/node_modules/dirty-chai/lib/dirty-chai.js"></script>
     <script src="/node_modules/mocha/mocha.js"></script>
     <script>
+      window.expect = chai.expect;
       mocha.setup('bdd');
     </script>
-
     <script src="/spec/env/json2.js"></script>
     <script src="/spec/env/require.js"></script>
 

From 0817dad7e72c51d07f7700547d0c69aa79a4976b Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Fri, 15 Nov 2019 17:22:29 +0100
Subject: [PATCH 4/9] test: add sinon as global variable to eslint in the specs

---
 spec/.eslintrc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/spec/.eslintrc b/spec/.eslintrc
index 8d4ed7a2e..4bec97f44 100644
--- a/spec/.eslintrc
+++ b/spec/.eslintrc
@@ -27,6 +27,7 @@
     "start": true,
     "stop": true,
     "ok": true,
+    "sinon": true,
     "strictEqual": true,
     "define": true,
     "expect": true,

From 886ba86c2f9cc71b7d99b9018fbe2d72a57085cc Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 17 Nov 2019 22:18:20 +0100
Subject: [PATCH 5/9] test/chore: add chai/expect and sinon to
 "runtime"-environment

---
 spec/env/runtime.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/spec/env/runtime.js b/spec/env/runtime.js
index 642acd348..4f6d28534 100644
--- a/spec/env/runtime.js
+++ b/spec/env/runtime.js
@@ -3,6 +3,15 @@ require('./common');
 var fs = require('fs'),
     vm = require('vm');
 
+var chai = require('chai');
+var dirtyChai = require('dirty-chai');
+
+
+chai.use(dirtyChai);
+global.expect = chai.expect;
+
+global.sinon = require('sinon');
+
 global.Handlebars = 'no-conflict';
 
 var filename = 'dist/handlebars.runtime.js';

From 198887808780bbef9dba67a8af68ece091d5baa7 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 17 Nov 2019 21:29:47 +0100
Subject: [PATCH 6/9] fix: add more properties required to be enumerable

- __defineGetter__, __defineSetter__, __lookupGetter__, __proto__
---
 lib/handlebars/compiler/compiler.js           | 15 ++--------
 .../compiler/javascript-compiler.js           |  6 ++--
 lib/handlebars/helpers/lookup.js              |  4 ++-
 spec/env/common.js                            | 29 +++++++++++++------
 spec/security.js                              | 24 +++++++++++++--
 5 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js
index 894f7a7c0..b56ca5c26 100644
--- a/lib/handlebars/compiler/compiler.js
+++ b/lib/handlebars/compiler/compiler.js
@@ -54,9 +54,7 @@ Compiler.prototype = {
 
     options.blockParams = options.blockParams || [];
 
-    // These changes will propagate to the other compiler components
-    let knownHelpers = options.knownHelpers;
-    options.knownHelpers = {
+    options.knownHelpers = extend(Object.create(null), {
       'helperMissing': true,
       'blockHelperMissing': true,
       'each': true,
@@ -65,15 +63,7 @@ Compiler.prototype = {
       'with': true,
       'log': true,
       'lookup': true
-    };
-    if (knownHelpers) {
-      // the next line should use "Object.keys", but the code has been like this a long time and changing it, might
-      // cause backwards-compatibility issues... It's an old library...
-      // eslint-disable-next-line guard-for-in
-      for (let name in knownHelpers) {
-          this.options.knownHelpers[name] = knownHelpers[name];
-      }
-    }
+    }, options.knownHelpers);
 
     return this.accept(program);
   },
@@ -369,7 +359,6 @@ Compiler.prototype = {
     if (isEligible && !isHelper) {
       let name = sexpr.path.parts[0],
           options = this.options;
-
       if (options.knownHelpers[name]) {
         isHelper = true;
       } else if (options.knownHelpersOnly) {
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js
index b21df1d8a..4acdb50dd 100644
--- a/lib/handlebars/compiler/javascript-compiler.js
+++ b/lib/handlebars/compiler/javascript-compiler.js
@@ -2,6 +2,7 @@ import { COMPILER_REVISION, REVISION_CHANGES } from '../base';
 import Exception from '../exception';
 import {isArray} from '../utils';
 import CodeGen from './code-gen';
+import {dangerousPropertyRegex} from '../helpers/lookup';
 
 function Literal(value) {
   this.value = value;
@@ -13,9 +14,8 @@ 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*/) {
-    const isEnumerable = [ this.aliasable('container.propertyIsEnumerable'), '.call(', parent, ',"constructor")'];
-
-    if (name === 'constructor') {
+    if (dangerousPropertyRegex.test(name)) {
+      const isEnumerable = [ this.aliasable('container.propertyIsEnumerable'), '.call(', parent, ',', JSON.stringify(name), ')'];
       return ['(', isEnumerable, '?', _actualLookup(), ' : undefined)'];
     }
     return _actualLookup();
diff --git a/lib/handlebars/helpers/lookup.js b/lib/handlebars/helpers/lookup.js
index 0654cc393..cba452451 100644
--- a/lib/handlebars/helpers/lookup.js
+++ b/lib/handlebars/helpers/lookup.js
@@ -1,9 +1,11 @@
+export const dangerousPropertyRegex = /^(constructor|__defineGetter__|__defineSetter__|__lookupGetter__|__proto__)$/;
+
 export default function(instance) {
   instance.registerHelper('lookup', function(obj, field) {
     if (!obj) {
       return obj;
     }
-    if (String(field) === 'constructor' && !obj.propertyIsEnumerable(field)) {
+    if (dangerousPropertyRegex.test(String(field)) && !obj.propertyIsEnumerable(field)) {
       return undefined;
     }
     return obj[field];
diff --git a/spec/env/common.js b/spec/env/common.js
index 3903e35d4..ac9421845 100644
--- a/spec/env/common.js
+++ b/spec/env/common.js
@@ -142,24 +142,35 @@ HandlebarsTestBench.prototype.withMessage = function(message) {
 };
 
 HandlebarsTestBench.prototype.toCompileTo = function(expectedOutputAsString) {
+  expect(this._compileAndExeute()).to.equal(expectedOutputAsString);
+};
+
+// see chai "to.throw" (https://www.chaijs.com/api/bdd/#method_throw)
+HandlebarsTestBench.prototype.toThrow = function(errorLike, errMsgMatcher, msg) {
   var self = this;
+  expect(function() {
+    self._compileAndExeute();
+  }).to.throw(errorLike, errMsgMatcher, msg);
+};
+
+HandlebarsTestBench.prototype._compileAndExeute = function() {
   var compile = Object.keys(this.partials).length > 0
       ? CompilerContext.compileWithPartial
       : CompilerContext.compile;
 
+  var combinedRuntimeOptions = this._combineRuntimeOptions();
+
+  var template = compile(this.templateAsString, this.compileOptions);
+  return template(this.input, combinedRuntimeOptions);
+};
+
+HandlebarsTestBench.prototype._combineRuntimeOptions = function() {
+  var self = this;
   var combinedRuntimeOptions = {};
   Object.keys(this.runtimeOptions).forEach(function(key) {
     combinedRuntimeOptions[key] = self.runtimeOptions[key];
   });
   combinedRuntimeOptions.helpers = this.helpers;
   combinedRuntimeOptions.partials = this.partials;
-
-  var template = compile(this.templateAsString, this.compileOptions);
-  var output = template(this.input, combinedRuntimeOptions);
-
-  if (output !== expectedOutputAsString) {
-    // Error message formatted so that IntelliJ-Idea shows "diff"-button
-    // https://stackoverflow.com/a/10945655/4251384
-    throw new AssertError(this.message + '\nexpected:' + expectedOutputAsString + 'but was:' + output);
-  }
+  return combinedRuntimeOptions;
 };
diff --git a/spec/security.js b/spec/security.js
index 876b67292..18bfa5dd7 100644
--- a/spec/security.js
+++ b/spec/security.js
@@ -114,13 +114,31 @@ describe('security issues', function() {
     describe('GH-1563', function() {
         it('should not allow to access constructor after overriding via __defineGetter__', function() {
             if (({}).__defineGetter__ == null || ({}).__lookupGetter__ == null) {
-                return; // Browser does not support this exploit anyway
+                return this.skip(); // Browser does not support this exploit anyway
             }
-            shouldCompileTo('{{__defineGetter__ "undefined" valueOf }}' +
+            expectTemplate('{{__defineGetter__ "undefined" valueOf }}' +
                 '{{#with __lookupGetter__ }}' +
                 '{{__defineGetter__ "propertyIsEnumerable" (this.bind (this.bind 1)) }}' +
                 '{{constructor.name}}' +
-                '{{/with}}', {}, '');
+                '{{/with}}')
+                .withInput({})
+                .toThrow(/Missing helper: "__defineGetter__"/);
         });
     });
+
+    describe('GH-1595', function() {
+      it('properties, that are required to be enumerable', function() {
+        expectTemplate('{{constructor}}').withInput({}).toCompileTo('');
+        expectTemplate('{{__defineGetter__}}').withInput({}).toCompileTo('');
+        expectTemplate('{{__defineSetter__}}').withInput({}).toCompileTo('');
+        expectTemplate('{{__lookupGetter__}}').withInput({}).toCompileTo('');
+        expectTemplate('{{__proto__}}').withInput({}).toCompileTo('');
+
+        expectTemplate('{{lookup "constructor"}}').withInput({}).toCompileTo('');
+        expectTemplate('{{lookup "__defineGetter__"}}').withInput({}).toCompileTo('');
+        expectTemplate('{{lookup "__defineSetter__"}}').withInput({}).toCompileTo('');
+        expectTemplate('{{lookup "__lookupGetter__"}}').withInput({}).toCompileTo('');
+        expectTemplate('{{lookup "__proto__"}}').withInput({}).toCompileTo('');
+      });
+    });
 });

From f7f05d7558e674856686b62a00cde5758f3b7a08 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Mon, 18 Nov 2019 04:14:54 +0100
Subject: [PATCH 7/9] fix: add "no-prototype-builtins" eslint-rule and fix all
 occurences

---
 .eslintrc.js                                  |  3 ++-
 bench/util/benchwarmer.js                     | 11 +++++-----
 lib/handlebars/compiler/code-gen.js           | 12 +++++------
 .../compiler/javascript-compiler.js           |  6 +++---
 lib/handlebars/helpers/each.js                | 20 +++++++++----------
 lib/handlebars/helpers/lookup.js              |  2 +-
 spec/compiler.js                              |  2 +-
 spec/regressions.js                           |  4 ++--
 8 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 3ba423055..5c55b10f9 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -57,6 +57,7 @@ module.exports = {
     "no-with": "error",
     "radix": "error",
     "wrap-iife": "error",
+    "no-prototype-builtins": "error",
 
 
     // Variables //
@@ -114,4 +115,4 @@ module.exports = {
     "ecmaVersion": 6,
     "ecmaFeatures": {}
   }
-}
+};
diff --git a/bench/util/benchwarmer.js b/bench/util/benchwarmer.js
index 49f66f737..58f138a0e 100644
--- a/bench/util/benchwarmer.js
+++ b/bench/util/benchwarmer.js
@@ -29,7 +29,7 @@ BenchWarmer.prototype = {
     });
   },
   push: function(name, fn) {
-    if (this.names.indexOf(name) == -1) {
+    if (this.names.indexOf(name) === -1) {
       this.names.push(name);
     }
 
@@ -77,7 +77,7 @@ BenchWarmer.prototype = {
 
         var errors = false, prop, bench;
         for (prop in self.errors) {
-          if (self.errors.hasOwnProperty(prop)
+          if (Object.prototype.hasOwnProperty.call(self, prop)
               && self.errors[prop].error.message !== 'EWOT') {
             errors = true;
             break;
@@ -86,9 +86,8 @@ BenchWarmer.prototype = {
 
         if (errors) {
           print('\n\nErrors:\n');
-          for (prop in self.errors) {
-            if (self.errors.hasOwnProperty(prop)
-                && self.errors[prop].error.message !== 'EWOT') {
+          Object.keys(self.errors).forEach(function(prop) {
+            if (self.errors[prop].error.message !== 'EWOT') {
               bench = self.errors[prop];
               print('\n' + bench.name + ':\n');
               print(bench.error.message);
@@ -97,7 +96,7 @@ BenchWarmer.prototype = {
               }
               print('\n');
             }
-          }
+          });
         }
 
         callback();
diff --git a/lib/handlebars/compiler/code-gen.js b/lib/handlebars/compiler/code-gen.js
index 43c0481bc..30c5af740 100644
--- a/lib/handlebars/compiler/code-gen.js
+++ b/lib/handlebars/compiler/code-gen.js
@@ -125,14 +125,12 @@ CodeGen.prototype = {
   objectLiteral: function(obj) {
     let pairs = [];
 
-    for (let key in obj) {
-      if (obj.hasOwnProperty(key)) {
-        let value = castChunk(obj[key], this);
-        if (value !== 'undefined') {
-          pairs.push([this.quotedString(key), ':', value]);
-        }
+    Object.keys(obj).forEach(key => {
+      let value = castChunk(obj[key], this);
+      if (value !== 'undefined') {
+        pairs.push([this.quotedString(key), ':', value]);
       }
-    }
+    });
 
     let ret = this.generateList(pairs);
     ret.prepend('{');
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js
index 4acdb50dd..9a4c02daf 100644
--- a/lib/handlebars/compiler/javascript-compiler.js
+++ b/lib/handlebars/compiler/javascript-compiler.js
@@ -218,13 +218,13 @@ JavaScriptCompiler.prototype = {
     // aliases will not be used, but this case is already being run on the client and
     // we aren't concern about minimizing the template size.
     let aliasCount = 0;
-    for (let alias in this.aliases) { // eslint-disable-line guard-for-in
+    Object.keys(this.aliases).forEach(alias => {
       let node = this.aliases[alias];
-      if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
+      if (node.children && node.referenceCount > 1) {
         varDeclarations += ', alias' + (++aliasCount) + '=' + alias;
         node.children[0] = 'alias' + aliasCount;
       }
-    }
+    });
 
     let params = ['container', 'depth0', 'helpers', 'partials', 'data'];
 
diff --git a/lib/handlebars/helpers/each.js b/lib/handlebars/helpers/each.js
index ce549b5c7..8e57b7782 100644
--- a/lib/handlebars/helpers/each.js
+++ b/lib/handlebars/helpers/each.js
@@ -62,18 +62,16 @@ export default function(instance) {
       } else {
         let priorKey;
 
-        for (let key in context) {
-          if (context.hasOwnProperty(key)) {
-            // We're running the iterations one step out of sync so we can detect
-            // the last iteration without have to scan the object twice and create
-            // an itermediate keys array.
-            if (priorKey !== undefined) {
-              execIteration(priorKey, i - 1);
-            }
-            priorKey = key;
-            i++;
+        Object.keys(context).forEach(key => {
+          // We're running the iterations one step out of sync so we can detect
+          // the last iteration without have to scan the object twice and create
+          // an itermediate keys array.
+          if (priorKey !== undefined) {
+            execIteration(priorKey, i - 1);
           }
-        }
+          priorKey = key;
+          i++;
+        });
         if (priorKey !== undefined) {
           execIteration(priorKey, i - 1, true);
         }
diff --git a/lib/handlebars/helpers/lookup.js b/lib/handlebars/helpers/lookup.js
index cba452451..8c1b604be 100644
--- a/lib/handlebars/helpers/lookup.js
+++ b/lib/handlebars/helpers/lookup.js
@@ -5,7 +5,7 @@ export default function(instance) {
     if (!obj) {
       return obj;
     }
-    if (dangerousPropertyRegex.test(String(field)) && !obj.propertyIsEnumerable(field)) {
+    if (dangerousPropertyRegex.test(String(field)) && !Object.prototype.propertyIsEnumerable.call(obj, field)) {
       return undefined;
     }
     return obj[field];
diff --git a/spec/compiler.js b/spec/compiler.js
index 02dad6751..3d37b5940 100644
--- a/spec/compiler.js
+++ b/spec/compiler.js
@@ -59,7 +59,7 @@ describe('compiler', function() {
         Handlebars.compile(' \n  {{#if}}\n{{/def}}')();
         equal(true, false, 'Statement must throw exception. This line should not be executed.');
       } catch (err) {
-        equal(err.propertyIsEnumerable('column'), true, 'Checking error column');
+        equal(Object.prototype.propertyIsEnumerable.call(err, 'column'), true, 'Checking error column');
       }
     });
 
diff --git a/spec/regressions.js b/spec/regressions.js
index a8879067e..74594de6b 100644
--- a/spec/regressions.js
+++ b/spec/regressions.js
@@ -211,12 +211,12 @@ describe('Regressions', function() {
         // It's valid to execute a block against an undefined context, but
         // helpers can not do so, so we expect to have an empty object here;
         for (var name in this) {
-          if (this.hasOwnProperty(name)) {
+          if (Object.prototype.hasOwnProperty.call(this, name)) {
             return 'found';
           }
         }
         // And to make IE happy, check for the known string as length is not enumerated.
-        return (this == 'bat' ? 'found' : 'not');
+        return (this === 'bat' ? 'found' : 'not');
       }
     };
 

From 827c9d0747bef7d7f89829779523b6b2dcf3051d Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Mon, 18 Nov 2019 08:09:48 +0100
Subject: [PATCH 8/9] Update release notes

---
 release-notes.md | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/release-notes.md b/release-notes.md
index 3eefabe89..199c39bf5 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -2,7 +2,49 @@
 
 ## Development
 
-[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.2...master)
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.3...master)
+
+## v4.5.3 - November 18th, 2019
+Bugfixes:
+
+- fix: add "no-prototype-builtins" eslint-rule and fix all occurences - f7f05d7
+- fix: add more properties required to be enumerable - 1988878
+
+Chores / Build:
+- fix: use !== 0 instead of != 0 - c02b05f
+- add chai and dirty-chai and sinon, for cleaner test-assertions and spies, 
+  deprecate old assertion-methods  - 93e284e, 886ba86, 0817dad, 93516a0
+
+Security:
+
+- The properties `__proto__`, `__defineGetter__`, `__defineSetter__` and `__lookupGetter__` 
+  have been added to the list of "properties that must be enumerable".
+  If a property by that name is found and not enumerable on its parent, 
+  it will silently evaluate to `undefined`. This is done in both the compiled template and the "lookup"-helper. 
+  This will prevent new Remote-Code-Execution exploits that have been
+  published recently.
+
+Compatibility notes: 
+
+- Due to the security-fixes. The semantics of the templates using
+  `__proto__`, `__defineGetter__`, `__defineSetter__` and `__lookupGetter__` in the respect that those expression now return 
+  `undefined` rather than their actual value from the proto.
+- The semantics have not changed in cases where the properties are  enumerable, as in:
+
+```js
+{
+  __proto__: 'some string'
+}
+```
+
+- The change may be breaking in that respect, but we still only 
+  increase the patch-version, because the incompatible use-cases
+  are not intended, undocumented and far less important than fixing
+  Remote-Code-Execution exploits on existing systems.
+
+
+
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.2...v4.5.3)
 
 ## v4.5.2 - November 13th, 2019
 # Bugfixes

From c819c8b533934d2ac18001d7eb27a3205b00c2f3 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Mon, 18 Nov 2019 08:10:26 +0100
Subject: [PATCH 9/9] v4.5.3

---
 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 53453c96d..07e2baa96 100644
--- a/components/bower.json
+++ b/components/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.2",
+  "version": "4.5.3",
   "main": "handlebars.js",
   "license": "MIT",
   "dependencies": {}
diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec
index a4ec49b01..e8d52d4ca 100644
--- a/components/handlebars.js.nuspec
+++ b/components/handlebars.js.nuspec
@@ -2,7 +2,7 @@
 <package>
 	<metadata>
 		<id>handlebars.js</id>
-		<version>4.5.2</version>
+		<version>4.5.3</version>
 		<authors>handlebars.js Authors</authors>
 		<licenseUrl>https://github.com/wycats/handlebars.js/blob/master/LICENSE</licenseUrl>
 		<projectUrl>https://github.com/wycats/handlebars.js/</projectUrl>
diff --git a/components/package.json b/components/package.json
index 1fcee3eed..9623086b4 100644
--- a/components/package.json
+++ b/components/package.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.2",
+  "version": "4.5.3",
   "license": "MIT",
   "jspm": {
     "main": "handlebars",
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index adb1547a5..ad3541b53 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.5.2';
+export const VERSION = '4.5.3';
 export const COMPILER_REVISION = 8;
 export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
 
diff --git a/package.json b/package.json
index 426b40cb2..74749d86b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "handlebars",
   "barename": "handlebars",
-  "version": "4.5.2",
+  "version": "4.5.3",
   "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
   "homepage": "http://www.handlebarsjs.com/",
   "keywords": [
