From 62ed3c25c76445deb8c51a5b36ce52f7f1be3411 Mon Sep 17 00:00:00 2001
From: Robert Jackson <me@rwjblue.com>
Date: Sun, 27 Oct 2019 19:28:28 -0400
Subject: [PATCH 1/9] Add Handlebars.parseWithoutProcessing (#1584)

When authoring tooling that parses Handlebars files and emits Handlebars
files, you often want to preserve the **exact** formatting of the input.
The changes in this commit add a new method to the `Handlebars`
namespace: `parseWithoutProcessing`. Unlike, `Handlebars.parse` (which
will mutate the parsed AST to apply whitespace control) this method will
parse the template and return it directly (**without** processing
:wink:).

For example, parsing the following template:

```hbs
 {{#foo}}
   {{~bar~}} {{baz~}}
 {{/foo}}
```

Using `Handlebars.parse`, the AST returned would have truncated the
following whitespace:

* The whitespace prior to the `{{#foo}}`
* The newline following `{{#foo}}`
* The leading whitespace before `{{~bar~}}`
* The whitespace between `{{~bar~}}` and `{{baz~}}`
* The newline after `{{baz~}}`
* The whitespace prior to the `{{/foo}}`

When `Handlebars.parse` is used from  `Handlebars.precompile` or
`Handlebars.compile`, this whitespace stripping is **very** important
(these behaviors are intentional, and generally lead to better rendered
output).

When the same template is parsed with
`Handlebars.parseWithoutProcessing` none of those modifications to the
AST are made. This enables "codemod tooling" (e.g. `prettier` and
`ember-template-recast`) to preserve the **exact** initial formatting.
Prior to these changes, those tools would have to _manually_ reconstruct
the whitespace that is lost prior to emitting source.
---
 docs/compiler-api.md            |  28 +++++++++
 lib/handlebars.js               |   3 +-
 lib/handlebars/compiler/base.js |  12 +++-
 spec/ast.js                     | 105 ++++++++++++++++++++++++++++++++
 types/index.d.ts                |   5 +-
 types/test.ts                   |  10 ++-
 6 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/docs/compiler-api.md b/docs/compiler-api.md
index f419fbcd..99b95069 100644
--- a/docs/compiler-api.md
+++ b/docs/compiler-api.md
@@ -16,6 +16,34 @@ var ast = Handlebars.parse(myTemplate);
 Handlebars.precompile(ast);
 ```
 
+### Parsing
+
+There are two primary APIs that are used to parse an existing template into the AST:
+
+#### parseWithoutProcessing
+
+`Handlebars.parseWithoutProcessing` is the primary mechanism to turn a raw template string into the Handlebars AST described in this document. No processing is done on the resulting AST which makes this ideal for codemod (for source to source transformation) tooling.
+
+Example:
+
+```js
+let ast = Handlebars.parseWithoutProcessing(myTemplate);
+```
+
+#### parse
+
+`Handlebars.parse` will parse the template with `parseWithoutProcessing` (see above) then it will update the AST to strip extraneous whitespace. The whitespace stripping functionality handles two distinct situations:
+
+* Removes whitespace around dynamic statements that are on a line by themselves (aka "stand alone")
+* Applies "whitespace control" characters (i.e. `~`) by truncating the `ContentStatement` `value` property appropriately (e.g. `\n\n{{~foo}}` would have a `ContentStatement` with a `value` of `''`)
+
+`Handlebars.parse` is used internally by `Handlebars.precompile` and `Handlebars.compile`.
+
+Example:
+
+```js
+let ast = Handlebars.parse(myTemplate);
+```
 
 ### Basic
 
diff --git a/lib/handlebars.js b/lib/handlebars.js
index f1149590..69bcb410 100644
--- a/lib/handlebars.js
+++ b/lib/handlebars.js
@@ -2,7 +2,7 @@ import runtime from './handlebars.runtime';
 
 // Compiler imports
 import AST from './handlebars/compiler/ast';
-import { parser as Parser, parse } from './handlebars/compiler/base';
+import { parser as Parser, parse, parseWithoutProcessing } from './handlebars/compiler/base';
 import { Compiler, compile, precompile } from './handlebars/compiler/compiler';
 import JavaScriptCompiler from './handlebars/compiler/javascript-compiler';
 import Visitor from './handlebars/compiler/visitor';
@@ -25,6 +25,7 @@ function create() {
   hb.JavaScriptCompiler = JavaScriptCompiler;
   hb.Parser = Parser;
   hb.parse = parse;
+  hb.parseWithoutProcessing = parseWithoutProcessing;
 
   return hb;
 }
diff --git a/lib/handlebars/compiler/base.js b/lib/handlebars/compiler/base.js
index c6871d39..19989ca5 100644
--- a/lib/handlebars/compiler/base.js
+++ b/lib/handlebars/compiler/base.js
@@ -8,7 +8,7 @@ export { parser };
 let yy = {};
 extend(yy, Helpers);
 
-export function parse(input, options) {
+export function parseWithoutProcessing(input, options) {
   // Just return if an already-compiled AST was passed in.
   if (input.type === 'Program') { return input; }
 
@@ -19,6 +19,14 @@ export function parse(input, options) {
     return new yy.SourceLocation(options && options.srcName, locInfo);
   };
 
+  let ast = parser.parse(input);
+
+  return ast;
+}
+
+export function parse(input, options) {
+  let ast = parseWithoutProcessing(input, options);
   let strip = new WhitespaceControl(options);
-  return strip.accept(parser.parse(input));
+
+  return strip.accept(ast);
 }
diff --git a/spec/ast.js b/spec/ast.js
index e43438be..09034739 100644
--- a/spec/ast.js
+++ b/spec/ast.js
@@ -123,6 +123,40 @@ describe('ast', function() {
      });
   });
 
+  describe('whitespace control', function() {
+    describe('parse', function() {
+      it('mustache', function() {
+        let ast = Handlebars.parse('  {{~comment~}} ');
+
+        equals(ast.body[0].value, '');
+        equals(ast.body[2].value, '');
+      });
+
+      it('block statements', function() {
+        var ast = Handlebars.parse(' {{# comment~}} \nfoo\n {{~/comment}}');
+
+        equals(ast.body[0].value, '');
+        equals(ast.body[1].program.body[0].value, 'foo');
+      });
+    });
+
+    describe('parseWithoutProcessing', function() {
+      it('mustache', function() {
+        let ast = Handlebars.parseWithoutProcessing('  {{~comment~}} ');
+
+        equals(ast.body[0].value, '  ');
+        equals(ast.body[2].value, ' ');
+      });
+
+      it('block statements', function() {
+        var ast = Handlebars.parseWithoutProcessing(' {{# comment~}} \nfoo\n {{~/comment}}');
+
+        equals(ast.body[0].value, ' ');
+        equals(ast.body[1].program.body[0].value, ' \nfoo\n ');
+      });
+    });
+  });
+
   describe('standalone flags', function() {
     describe('mustache', function() {
       it('does not mark mustaches as standalone', function() {
@@ -131,6 +165,54 @@ describe('ast', function() {
         equals(!!ast.body[2].value, true);
       });
     });
+    describe('blocks - parseWithoutProcessing', function() {
+      it('block mustaches', function() {
+        var ast = Handlebars.parseWithoutProcessing(' {{# comment}} \nfoo\n {{else}} \n  bar \n  {{/comment}} '),
+          block = ast.body[1];
+
+        equals(ast.body[0].value, ' ');
+
+        equals(block.program.body[0].value, ' \nfoo\n ');
+        equals(block.inverse.body[0].value, ' \n  bar \n  ');
+
+        equals(ast.body[2].value, ' ');
+      });
+      it('initial block mustaches', function() {
+        var ast = Handlebars.parseWithoutProcessing('{{# comment}} \nfoo\n {{/comment}}'),
+          block = ast.body[0];
+
+        equals(block.program.body[0].value, ' \nfoo\n ');
+      });
+      it('mustaches with children', function() {
+        var ast = Handlebars.parseWithoutProcessing('{{# comment}} \n{{foo}}\n {{/comment}}'),
+          block = ast.body[0];
+
+        equals(block.program.body[0].value, ' \n');
+        equals(block.program.body[1].path.original, 'foo');
+        equals(block.program.body[2].value, '\n ');
+      });
+      it('nested block mustaches', function() {
+        var ast = Handlebars.parseWithoutProcessing('{{#foo}} \n{{# comment}} \nfoo\n {{else}} \n  bar \n  {{/comment}} \n{{/foo}}'),
+          body = ast.body[0].program.body,
+          block = body[1];
+
+        equals(body[0].value, ' \n');
+
+        equals(block.program.body[0].value, ' \nfoo\n ');
+        equals(block.inverse.body[0].value, ' \n  bar \n  ');
+      });
+      it('column 0 block mustaches', function() {
+        var ast = Handlebars.parseWithoutProcessing('test\n{{# comment}} \nfoo\n {{else}} \n  bar \n  {{/comment}} '),
+            block = ast.body[1];
+
+        equals(ast.body[0].omit, undefined);
+
+        equals(block.program.body[0].value, ' \nfoo\n ');
+        equals(block.inverse.body[0].value, ' \n  bar \n  ');
+
+        equals(ast.body[2].value, ' ');
+      });
+    });
     describe('blocks', function() {
       it('marks block mustaches as standalone', function() {
         var ast = Handlebars.parse(' {{# comment}} \nfoo\n {{else}} \n  bar \n  {{/comment}} '),
@@ -204,6 +286,18 @@ describe('ast', function() {
         equals(ast.body[2].value, '');
       });
     });
+    describe('partials - parseWithoutProcessing', function() {
+      it('simple partial', function() {
+        var ast = Handlebars.parseWithoutProcessing('{{> partial }} ');
+        equals(ast.body[1].value, ' ');
+      });
+      it('indented partial', function() {
+        var ast = Handlebars.parseWithoutProcessing('  {{> partial }} ');
+        equals(ast.body[0].value, '  ');
+        equals(ast.body[1].indent, '');
+        equals(ast.body[2].value, ' ');
+      });
+    });
     describe('partials', function() {
       it('marks partial as standalone', function() {
         var ast = Handlebars.parse('{{> partial }} ');
@@ -223,6 +317,17 @@ describe('ast', function() {
         equals(ast.body[1].omit, undefined);
       });
     });
+    describe('comments - parseWithoutProcessing', function() {
+      it('simple comment', function() {
+        var ast = Handlebars.parseWithoutProcessing('{{! comment }} ');
+        equals(ast.body[1].value, ' ');
+      });
+      it('indented comment', function() {
+        var ast = Handlebars.parseWithoutProcessing('  {{! comment }} ');
+        equals(ast.body[0].value, '  ');
+        equals(ast.body[2].value, ' ');
+      });
+    });
     describe('comments', function() {
       it('marks comment as standalone', function() {
         var ast = Handlebars.parse('{{! comment }} ');
diff --git a/types/index.d.ts b/types/index.d.ts
index 6fdaf0f9..00e04d42 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -47,8 +47,8 @@ declare namespace Handlebars {
   }
 
   export interface ParseOptions {
-      srcName?: string,
-      ignoreStandalone?: boolean
+      srcName?: string;
+      ignoreStandalone?: boolean;
   }
 
   export function registerHelper(name: string, fn: HelperDelegate): void;
@@ -69,6 +69,7 @@ declare namespace Handlebars {
   export function Exception(message: string): void;
   export function log(level: number, obj: any): void;
   export function parse(input: string, options?: ParseOptions): hbs.AST.Program;
+  export function parseWithoutProcessing(input: string, options?: ParseOptions): hbs.AST.Program;
   export function compile<T = any>(input: any, options?: CompileOptions): HandlebarsTemplateDelegate<T>;
   export function precompile(input: any, options?: PrecompileOptions): TemplateSpecification;
   export function template<T = any>(precompilation: TemplateSpecification): HandlebarsTemplateDelegate<T>;
diff --git a/types/test.ts b/types/test.ts
index ff435916..cef0d598 100644
--- a/types/test.ts
+++ b/types/test.ts
@@ -192,4 +192,12 @@ switch(allthings.type) {
     break;
   default:
     break;
-}
\ No newline at end of file
+}
+
+function testParseWithoutProcessing() {
+  const parsedTemplate: hbs.AST.Program = Handlebars.parseWithoutProcessing('<p>Hello, my name is {{name}}.</p>', {
+    srcName: "/foo/bar/baz.hbs",
+  });
+
+  const parsedTemplateWithoutOptions: hbs.AST.Program = Handlebars.parseWithoutProcessing('<p>Hello, my name is {{name}}.</p>');
+}

From b8913fcc6598ee7e6d1ef5f1dec98a002f0c36c6 Mon Sep 17 00:00:00 2001
From: Kabir Baidhya <kabirbaidhya@gmail.com>
Date: Mon, 28 Oct 2019 20:43:59 +0545
Subject: [PATCH 2/9] Add missing types for the Exception class properties
 (#1583)

* Convert Exception to a class
* Add node param type declaration
* Test the types
---
 types/index.d.ts | 15 ++++++++++++++-
 types/test.ts    | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/types/index.d.ts b/types/index.d.ts
index 00e04d42..bb0656a5 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -66,7 +66,6 @@ declare namespace Handlebars {
   export function K(): void;
   export function createFrame(object: any): any;
   export function blockParams(obj: any[], ids: any[]): any[];
-  export function Exception(message: string): void;
   export function log(level: number, obj: any): void;
   export function parse(input: string, options?: ParseOptions): hbs.AST.Program;
   export function parseWithoutProcessing(input: string, options?: ParseOptions): hbs.AST.Program;
@@ -87,6 +86,20 @@ declare namespace Handlebars {
 
   export function noConflict(): typeof Handlebars;
 
+  export class Exception {
+      constructor(message: string, node?: hbs.AST.Node);
+      description: string;
+      fileName: string;
+      lineNumber?: any;
+      endLineNumber?: any;
+      message: string;
+      name: string;
+      number: number;
+      stack?: string;
+      column?: any;
+      endColumn?: any;
+  }
+
   export class SafeString {
       constructor(str: string);
       toString(): string;
diff --git a/types/test.ts b/types/test.ts
index cef0d598..fa983268 100644
--- a/types/test.ts
+++ b/types/test.ts
@@ -201,3 +201,42 @@ function testParseWithoutProcessing() {
 
   const parsedTemplateWithoutOptions: hbs.AST.Program = Handlebars.parseWithoutProcessing('<p>Hello, my name is {{name}}.</p>');
 }
+
+function testExceptionTypings() {
+  // Test exception constructor with a single argument - message.
+  let exception: Handlebars.Exception = new Handlebars.Exception('message');
+
+  // Fields
+  let message: string = exception.message;
+  let lineNumber: number = exception.lineNumber;
+  let column: number = exception.column;
+  let endLineNumber: number = exception.endLineNumber;
+  let endColumn: number = exception.endColumn;
+  let description = exception.description;
+  let name: string = exception.name;
+  let fileName: string = exception.fileName;
+  let stack: string | undefined = exception.stack;
+}
+
+function testExceptionWithNodeTypings() {
+  // Test exception constructor with both arguments.
+  const exception: Handlebars.Exception = new Handlebars.Exception('message', {
+    type: 'MustacheStatement',
+    loc: {
+      source: 'source',
+      start: { line: 1, column: 5 },
+      end: { line: 10, column: 2 }
+    }
+  });
+
+  // Fields
+  let message: string = exception.message;
+  let lineNumber: number = exception.lineNumber;
+  let column: number = exception.column;
+  let endLineNumber: number = exception.endLineNumber;
+  let endColumn: number = exception.endColumn;
+  let description = exception.description;
+  let name: string = exception.name;
+  let fileName: string = exception.fileName;
+  let stack: string | undefined = exception.stack;
+}

From 7052e88068025aa5547f3c96d740283045bbbc2c Mon Sep 17 00:00:00 2001
From: Kabir Baidhya <kabirbaidhya@gmail.com>
Date: Mon, 28 Oct 2019 23:17:49 +0545
Subject: [PATCH 3/9] Resolve deprecation warning message from eslint while
 running eslint (#1586)

* Resolve eslint deprecation warning

  There was a DeprecationWarning message from eslint saying that `ecmaFeatures` property has
  been deprecated.
  Moved it under the `parserOptions` as per recommended here -
  https://eslint.org/docs/user-guide/migrating-to-2.0.0.
* Set escmaVersion = 6
* Use ES6 built-in global variables
* Remove flags in favor of ecmaVersion
---
 .eslintrc.js | 24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 34daed78..0b71556f 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -4,22 +4,8 @@ module.exports = {
     "self": false
   },
   "env": {
-    "node": true
-  },
-  "ecmaFeatures": {
-    // Enabling features that can be implemented without polyfills. Want to avoid polyfills at this time.
-    "arrowFunctions": true,
-    "blockBindings": true,
-    "defaultParams": true,
-    "destructuring": true,
-    "modules": true,
-    "objectLiteralComputedProperties": true,
-    "objectLiteralDuplicateProperties": true,
-    "objectLiteralShorthandMethods": true,
-    "objectLiteralShorthandProperties": true,
-    "restParams": true,
-    "spread": true,
-    "templateStrings": true
+    "node": true,
+    "es6": true
   },
   "rules": {
     // overrides eslint:recommended defaults
@@ -124,6 +110,8 @@ module.exports = {
     "no-var": "warn"
   },
   "parserOptions": {
-    "sourceType": "module"
+    "sourceType": "module",
+    "ecmaVersion": 6,
+    "ecmaFeatures": {}
   }
-}
\ No newline at end of file
+}

From 088e61812a111f5c0ebf1e583852bc6640efcc3a Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Mon, 28 Oct 2019 19:17:57 +0100
Subject: [PATCH 4/9] chore: add eslint-plugin-compat and eslint-plugin-es5

- tests are not compiled with babel and must thus be in
  es5
- we don't use polyfills, so we need to make sure no
  functions aren't used that are not supported by popular browsers. (like Object.assign in Safari and IE11)
- Boths are errors that usually only appear when running
  tests in SauceLabs, which happens only on _after_
  merging a PR.
---
 .eslintrc.js        |   2 +-
 package-lock.json   | 103 ++++++++++++++++++++++++++++++++++++++++++--
 package.json        |   2 +
 spec/.eslintrc      |   9 +++-
 spec/ast.js         |   4 +-
 spec/env/browser.js |   2 +-
 6 files changed, 113 insertions(+), 9 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 0b71556f..3ba42305 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,5 +1,5 @@
 module.exports = {
-  "extends": "eslint:recommended",
+  "extends": ["eslint:recommended","plugin:compat/recommended"],
   "globals": {
     "self": false
   },
diff --git a/package-lock.json b/package-lock.json
index c884c05e..d975d751 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,9 +1,17 @@
 {
   "name": "handlebars",
-  "version": "4.4.1",
+  "version": "4.4.5",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@babel/runtime": {
+      "version": "7.6.3",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
+      "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
+      "requires": {
+        "regenerator-runtime": "^0.13.2"
+      }
+    },
     "@knappi/grunt-saucelabs": {
       "version": "9.0.2",
       "resolved": "https://registry.npmjs.org/@knappi/grunt-saucelabs/-/grunt-saucelabs-9.0.2.tgz",
@@ -321,6 +329,11 @@
       "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
       "dev": true
     },
+    "ast-metadata-inferer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.1.1.tgz",
+      "integrity": "sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw=="
+    },
     "ast-traverse": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz",
@@ -832,6 +845,16 @@
         "pako": "~0.2.0"
       }
     },
+    "browserslist": {
+      "version": "4.7.2",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz",
+      "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==",
+      "requires": {
+        "caniuse-lite": "^1.0.30001004",
+        "electron-to-chromium": "^1.3.295",
+        "node-releases": "^1.1.38"
+      }
+    },
     "buffer": {
       "version": "4.9.1",
       "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
@@ -931,6 +954,16 @@
         }
       }
     },
+    "caniuse-db": {
+      "version": "1.0.30001005",
+      "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001005.tgz",
+      "integrity": "sha512-MSRfm2N6FRDSpAJ00ipCuFe0CNink5JJOFzl4S7fLSBJdowhGq3uMxzkWGTjvvReo1PuWfK5YYJydJJ+9mJebw=="
+    },
+    "caniuse-lite": {
+      "version": "1.0.30001005",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001005.tgz",
+      "integrity": "sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg=="
+    },
     "caseless": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -1747,6 +1780,11 @@
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
       "dev": true
     },
+    "electron-to-chromium": {
+      "version": "1.3.296",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.296.tgz",
+      "integrity": "sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ=="
+    },
     "emojis-list": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
@@ -2067,6 +2105,33 @@
         }
       }
     },
+    "eslint-plugin-compat": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.3.0.tgz",
+      "integrity": "sha512-QCgYy3pZ+zH10dkBJus1xER0359h1UhJjufhQRqp9Owm6BEoLZeSqxf2zINwL1OGao9Yc96xPYIW3nQj5HUryg==",
+      "requires": {
+        "@babel/runtime": "^7.4.5",
+        "ast-metadata-inferer": "^0.1.1",
+        "browserslist": "^4.6.3",
+        "caniuse-db": "^1.0.30000977",
+        "lodash.memoize": "4.1.2",
+        "mdn-browser-compat-data": "^0.0.84",
+        "semver": "^6.1.2"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+        }
+      }
+    },
+    "eslint-plugin-es5": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es5/-/eslint-plugin-es5-1.4.1.tgz",
+      "integrity": "sha512-kktkmkF2O7pnSZYgrMiYMbt3wCKRIiXePwILv8USDG95YgP0PzhIxSIROLLKmiQQ/Z6LuhDGWTHK04gnbXBvkg==",
+      "dev": true
+    },
     "eslint-scope": {
       "version": "3.7.3",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
@@ -2295,8 +2360,7 @@
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-      "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=",
-      "dev": true
+      "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo="
     },
     "extend-shallow": {
       "version": "3.0.2",
@@ -5129,6 +5193,11 @@
       "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
       "dev": true
     },
+    "lodash.memoize": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+      "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
+    },
     "longest": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -5220,6 +5289,14 @@
         "pretty-bytes": "^1.0.0"
       }
     },
+    "mdn-browser-compat-data": {
+      "version": "0.0.84",
+      "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.84.tgz",
+      "integrity": "sha512-fAznuGNaQMQiWLVf+gyp33FaABTglYWqMT7JqvH+4RZn2UQPD12gbMqxwP9m0lj8AAbNpu5/kD6n4Ox1SOffpw==",
+      "requires": {
+        "extend": "3.0.2"
+      }
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -5622,6 +5699,21 @@
         }
       }
     },
+    "node-releases": {
+      "version": "1.1.39",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz",
+      "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==",
+      "requires": {
+        "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+        }
+      }
+    },
     "nomnom": {
       "version": "0.4.3",
       "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-0.4.3.tgz",
@@ -6746,6 +6838,11 @@
         "through": "~2.3.8"
       }
     },
+    "regenerator-runtime": {
+      "version": "0.13.3",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+      "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
+    },
     "regex-cache": {
       "version": "0.4.4",
       "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
diff --git a/package.json b/package.json
index 40391a61..04f8cb4a 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "node": ">=0.4.7"
   },
   "dependencies": {
+    "eslint-plugin-compat": "^3.3.0",
     "neo-async": "^2.6.0",
     "optimist": "^0.6.1",
     "source-map": "^0.6.1"
@@ -37,6 +38,7 @@
     "dtslint": "^0.5.5",
     "dustjs-linkedin": "^2.0.2",
     "eco": "~1.1.0-rc-3",
+    "eslint-plugin-es5": "^1.4.1",
     "grunt": "^1.0.3",
     "grunt-babel": "^5.0.0",
     "grunt-bg-shell": "^2.3.3",
diff --git a/spec/.eslintrc b/spec/.eslintrc
index 21871d52..421bd00d 100644
--- a/spec/.eslintrc
+++ b/spec/.eslintrc
@@ -1,14 +1,19 @@
 {
+  "extends": [
+    "../.eslintrc.js",
+    "plugin:es5/no-es2015"
+  ],
+  "plugins": [
+    "es5"
+  ],
   "globals": {
     "CompilerContext": true,
     "Handlebars": true,
     "handlebarsEnv": true,
-
     "shouldCompileTo": true,
     "shouldCompileToWithPartials": true,
     "shouldThrow": true,
     "compileWithPartials": true,
-
     "console": true,
     "require": true,
     "suite": true,
diff --git a/spec/ast.js b/spec/ast.js
index 09034739..ffd0a958 100644
--- a/spec/ast.js
+++ b/spec/ast.js
@@ -126,7 +126,7 @@ describe('ast', function() {
   describe('whitespace control', function() {
     describe('parse', function() {
       it('mustache', function() {
-        let ast = Handlebars.parse('  {{~comment~}} ');
+        var ast = Handlebars.parse('  {{~comment~}} ');
 
         equals(ast.body[0].value, '');
         equals(ast.body[2].value, '');
@@ -142,7 +142,7 @@ describe('ast', function() {
 
     describe('parseWithoutProcessing', function() {
       it('mustache', function() {
-        let ast = Handlebars.parseWithoutProcessing('  {{~comment~}} ');
+        var ast = Handlebars.parseWithoutProcessing('  {{~comment~}} ');
 
         equals(ast.body[0].value, '  ');
         equals(ast.body[2].value, ' ');
diff --git a/spec/env/browser.js b/spec/env/browser.js
index 8b89207e..9e54a397 100644
--- a/spec/env/browser.js
+++ b/spec/env/browser.js
@@ -9,7 +9,7 @@ var filename = 'dist/handlebars.js';
 if (global.minimizedTest) {
   filename = 'dist/handlebars.min.js';
 }
-var distHandlebars = fs.readFileSync(require.resolve(`../../${filename}`), 'utf-8');
+var distHandlebars = fs.readFileSync(require.resolve('../../' + filename), 'utf-8');
 vm.runInThisContext(distHandlebars, filename);
 
 global.CompilerContext = {

From a2430678830fa4f2fc207fac1453e805908f60de Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Mon, 28 Oct 2019 19:47:08 +0100
Subject: [PATCH 5/9] Update release notes

---
 release-notes.md | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/release-notes.md b/release-notes.md
index 4d5bfbf6..7f4275f8 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -2,7 +2,25 @@
 
 ## Development
 
-[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.5...master)
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.0...master)
+
+## v4.5.0 - October 28th, 2019
+Features / Improvements
+- Add method Handlebars.parseWithoutProcessing (#1584) - 62ed3c2
+- add guard to if & unless helpers (#1549)
+- show source location for the strict lookup exceptions - feb60f8
+
+Bugfixes:
+- Use objects for hash value tracking - 7fcf9d2
+
+Chore:
+- Resolve deprecation warning message from eslint while running eslint (#1586) - 7052e88
+- chore: add eslint-plugin-compat and eslint-plugin-es5 - 088e618
+
+Compatibility notes:
+- No compatibility issues are to be expected
+
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.5...v4.5.0)
 
 ## v4.4.5 - October 20th, 2019
 Bugfixes: 

From b24797da01afd4e849fdb315dea8335792974522 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Mon, 28 Oct 2019 19:47:51 +0100
Subject: [PATCH 6/9] v4.5.0

---
 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 de0d3edf..d14dea96 100644
--- a/components/bower.json
+++ b/components/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.4.5",
+  "version": "4.5.0",
   "main": "handlebars.js",
   "license": "MIT",
   "dependencies": {}
diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec
index 5c03a079..2888f1c6 100644
--- a/components/handlebars.js.nuspec
+++ b/components/handlebars.js.nuspec
@@ -2,7 +2,7 @@
 <package>
 	<metadata>
 		<id>handlebars.js</id>
-		<version>4.4.5</version>
+		<version>4.5.0</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 db8c6a63..e0f6b098 100644
--- a/components/package.json
+++ b/components/package.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.4.5",
+  "version": "4.5.0",
   "license": "MIT",
   "jspm": {
     "main": "handlebars",
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index eccdb475..c3b1384b 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.4.5';
+export const VERSION = '4.5.0';
 export const COMPILER_REVISION = 8;
 export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
 
diff --git a/package.json b/package.json
index 04f8cb4a..90a75d00 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "handlebars",
   "barename": "handlebars",
-  "version": "4.4.5",
+  "version": "4.5.0",
   "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
   "homepage": "http://www.handlebarsjs.com/",
   "keywords": [

From 5e9d17f8faf770efb892a526603a728e480a9349 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Tue, 29 Oct 2019 05:17:03 +0100
Subject: [PATCH 7/9] fix: move "eslint-plugin-compat" to devDependencies

---
 package-lock.json | 34 ++++++++++++++++++++++++----------
 package.json      |  2 +-
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index d975d751..332d8fb1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.4.5",
+  "version": "4.5.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -8,6 +8,7 @@
       "version": "7.6.3",
       "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
       "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
+      "dev": true,
       "requires": {
         "regenerator-runtime": "^0.13.2"
       }
@@ -332,7 +333,8 @@
     "ast-metadata-inferer": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.1.1.tgz",
-      "integrity": "sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw=="
+      "integrity": "sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw==",
+      "dev": true
     },
     "ast-traverse": {
       "version": "0.1.1",
@@ -849,6 +851,7 @@
       "version": "4.7.2",
       "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz",
       "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==",
+      "dev": true,
       "requires": {
         "caniuse-lite": "^1.0.30001004",
         "electron-to-chromium": "^1.3.295",
@@ -957,12 +960,14 @@
     "caniuse-db": {
       "version": "1.0.30001005",
       "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001005.tgz",
-      "integrity": "sha512-MSRfm2N6FRDSpAJ00ipCuFe0CNink5JJOFzl4S7fLSBJdowhGq3uMxzkWGTjvvReo1PuWfK5YYJydJJ+9mJebw=="
+      "integrity": "sha512-MSRfm2N6FRDSpAJ00ipCuFe0CNink5JJOFzl4S7fLSBJdowhGq3uMxzkWGTjvvReo1PuWfK5YYJydJJ+9mJebw==",
+      "dev": true
     },
     "caniuse-lite": {
       "version": "1.0.30001005",
       "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001005.tgz",
-      "integrity": "sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg=="
+      "integrity": "sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg==",
+      "dev": true
     },
     "caseless": {
       "version": "0.12.0",
@@ -1783,7 +1788,8 @@
     "electron-to-chromium": {
       "version": "1.3.296",
       "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.296.tgz",
-      "integrity": "sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ=="
+      "integrity": "sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ==",
+      "dev": true
     },
     "emojis-list": {
       "version": "2.1.0",
@@ -2109,6 +2115,7 @@
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.3.0.tgz",
       "integrity": "sha512-QCgYy3pZ+zH10dkBJus1xER0359h1UhJjufhQRqp9Owm6BEoLZeSqxf2zINwL1OGao9Yc96xPYIW3nQj5HUryg==",
+      "dev": true,
       "requires": {
         "@babel/runtime": "^7.4.5",
         "ast-metadata-inferer": "^0.1.1",
@@ -2122,7 +2129,8 @@
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
         }
       }
     },
@@ -2360,7 +2368,8 @@
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-      "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo="
+      "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=",
+      "dev": true
     },
     "extend-shallow": {
       "version": "3.0.2",
@@ -5196,7 +5205,8 @@
     "lodash.memoize": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-      "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
+      "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+      "dev": true
     },
     "longest": {
       "version": "1.0.1",
@@ -5293,6 +5303,7 @@
       "version": "0.0.84",
       "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.84.tgz",
       "integrity": "sha512-fAznuGNaQMQiWLVf+gyp33FaABTglYWqMT7JqvH+4RZn2UQPD12gbMqxwP9m0lj8AAbNpu5/kD6n4Ox1SOffpw==",
+      "dev": true,
       "requires": {
         "extend": "3.0.2"
       }
@@ -5703,6 +5714,7 @@
       "version": "1.1.39",
       "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz",
       "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==",
+      "dev": true,
       "requires": {
         "semver": "^6.3.0"
       },
@@ -5710,7 +5722,8 @@
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
         }
       }
     },
@@ -6841,7 +6854,8 @@
     "regenerator-runtime": {
       "version": "0.13.3",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
-      "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
+      "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+      "dev": true
     },
     "regex-cache": {
       "version": "0.4.4",
diff --git a/package.json b/package.json
index 90a75d00..b1425af2 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,6 @@
     "node": ">=0.4.7"
   },
   "dependencies": {
-    "eslint-plugin-compat": "^3.3.0",
     "neo-async": "^2.6.0",
     "optimist": "^0.6.1",
     "source-map": "^0.6.1"
@@ -38,6 +37,7 @@
     "dtslint": "^0.5.5",
     "dustjs-linkedin": "^2.0.2",
     "eco": "~1.1.0-rc-3",
+    "eslint-plugin-compat": "^3.3.0",
     "eslint-plugin-es5": "^1.4.1",
     "grunt": "^1.0.3",
     "grunt-babel": "^5.0.0",

From b75e3e1f403f0564a43fc9ffa759fbe1afccd1c1 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Tue, 29 Oct 2019 05:41:43 +0100
Subject: [PATCH 8/9] Update release notes

---
 release-notes.md | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/release-notes.md b/release-notes.md
index 7f4275f8..11b1d014 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -2,7 +2,18 @@
 
 ## Development
 
-[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.0...master)
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.1...master)
+
+## v4.5.1 - October 29th, 2019
+Bugfixs
+
+- fix: move "eslint-plugin-compat" to devDependencies - 5e9d17f (#1589)
+
+Compatibility notes:
+- No compatibility issues are to be expected
+
+
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.0...v4.5.1)
 
 ## v4.5.0 - October 28th, 2019
 Features / Improvements

From 7ef86173abb446cf564ad6dc2646a4c361e2ab9f Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Tue, 29 Oct 2019 05:42:23 +0100
Subject: [PATCH 9/9] v4.5.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 d14dea96..fada3225 100644
--- a/components/bower.json
+++ b/components/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.0",
+  "version": "4.5.1",
   "main": "handlebars.js",
   "license": "MIT",
   "dependencies": {}
diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec
index 2888f1c6..d7a2dffe 100644
--- a/components/handlebars.js.nuspec
+++ b/components/handlebars.js.nuspec
@@ -2,7 +2,7 @@
 <package>
 	<metadata>
 		<id>handlebars.js</id>
-		<version>4.5.0</version>
+		<version>4.5.1</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 e0f6b098..a13ff027 100644
--- a/components/package.json
+++ b/components/package.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.0",
+  "version": "4.5.1",
   "license": "MIT",
   "jspm": {
     "main": "handlebars",
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index c3b1384b..fcf71a2b 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.0';
+export const VERSION = '4.5.1';
 export const COMPILER_REVISION = 8;
 export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
 
diff --git a/package.json b/package.json
index b1425af2..2cb199f3 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "handlebars",
   "barename": "handlebars",
-  "version": "4.5.0",
+  "version": "4.5.1",
   "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
   "homepage": "http://www.handlebarsjs.com/",
   "keywords": [
