From 3c1e2521694583bc1d8bade1ed5b162f5bfb065a Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 12 Jan 2020 13:06:56 +0100
Subject: [PATCH 1/4] fix: log error for illegal property access only once per
 property

---
 lib/handlebars/base.js                  |  8 +++++++
 lib/handlebars/internal/proto-access.js | 28 ++++++++++++++++++-------
 spec/security.js                        | 21 +++++++++++++++++++
 3 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index a80e0dde4..6e58ad8b4 100644
--- a/lib/handlebars/base.js
+++ b/lib/handlebars/base.js
@@ -3,6 +3,7 @@ import Exception from './exception';
 import { registerDefaultHelpers } from './helpers';
 import { registerDefaultDecorators } from './decorators';
 import logger from './logger';
+import { resetLoggedProperties } from './internal/proto-access';
 
 export const VERSION = '4.7.0';
 export const COMPILER_REVISION = 8;
@@ -78,6 +79,13 @@ HandlebarsEnvironment.prototype = {
   },
   unregisterDecorator: function(name) {
     delete this.decorators[name];
+  },
+  /**
+   * Reset the memory of illegal property accesses that have already been logged.
+   * @deprecated should only be used in handlebars test-cases
+   */
+  resetLoggedPropertyAccesses() {
+    resetLoggedProperties();
   }
 };
 
diff --git a/lib/handlebars/internal/proto-access.js b/lib/handlebars/internal/proto-access.js
index a10f5124c..7bf9553f3 100644
--- a/lib/handlebars/internal/proto-access.js
+++ b/lib/handlebars/internal/proto-access.js
@@ -1,6 +1,8 @@
 import { createNewLookupObject } from './create-new-lookup-object';
 import * as logger from '../logger';
 
+const loggedProperties = Object.create(null);
+
 export function createProtoAccessControl(runtimeOptions) {
   let defaultMethodWhiteList = Object.create(null);
   defaultMethodWhiteList['constructor'] = false;
@@ -45,12 +47,24 @@ function checkWhiteList(protoAccessControlForType, propertyName) {
   if (protoAccessControlForType.defaultValue !== undefined) {
     return protoAccessControlForType.defaultValue;
   }
-  // eslint-disable-next-line no-console
-  logger.log(
-    'error',
-    `Handlebars: Access has been denied to resolve the property "${propertyName}" because it is not an "own property" of its parent.\n` +
-      `You can add a runtime option to disable the check or this warning:\n` +
-      `See http://localhost:8080/api-reference/runtime-options.html#options-to-control-prototype-access for details`
-  );
+  logUnexpecedPropertyAccessOnce(propertyName);
   return false;
 }
+
+function logUnexpecedPropertyAccessOnce(propertyName) {
+  if (loggedProperties[propertyName] !== true) {
+    loggedProperties[propertyName] = true;
+    logger.log(
+      'error',
+      `Handlebars: Access has been denied to resolve the property "${propertyName}" because it is not an "own property" of its parent.\n` +
+        `You can add a runtime option to disable the check or this warning:\n` +
+        `See http://localhost:8080/api-reference/runtime-options.html#options-to-control-prototype-access for details`
+    );
+  }
+}
+
+export function resetLoggedProperties() {
+  Object.keys(loggedProperties).forEach(propertyName => {
+    delete loggedProperties[propertyName];
+  });
+}
diff --git a/spec/security.js b/spec/security.js
index bf0be1485..1b345f0cc 100644
--- a/spec/security.js
+++ b/spec/security.js
@@ -190,6 +190,10 @@ describe('security issues', function() {
       return 'returnValue';
     };
 
+    beforeEach(function() {
+      handlebarsEnv.resetLoggedPropertyAccesses();
+    });
+
     afterEach(function() {
       sinon.restore();
     });
@@ -214,6 +218,23 @@ describe('security issues', function() {
           expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
         });
 
+        it('should only log the warning once', function() {
+          var spy = sinon.spy(console, 'error');
+
+          expectTemplate('{{aMethod}}')
+            .withInput(new TestClass())
+            .withCompileOptions(compileOptions)
+            .toCompileTo('');
+
+          expectTemplate('{{aMethod}}')
+            .withInput(new TestClass())
+            .withCompileOptions(compileOptions)
+            .toCompileTo('');
+
+          expect(spy.calledOnce).to.be.true();
+          expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
+        });
+
         it('can be allowed, which disables the warning', function() {
           var spy = sinon.spy(console, 'error');
 

From f152dfc89204e8c117605d602dac4fdc174ddcd9 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 12 Jan 2020 13:09:19 +0100
Subject: [PATCH 2/4] fix: fix log output in case of illegal property access

- fix link url to handlebarsjs.com
---
 lib/handlebars/internal/proto-access.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/handlebars/internal/proto-access.js b/lib/handlebars/internal/proto-access.js
index 7bf9553f3..a8c5394d5 100644
--- a/lib/handlebars/internal/proto-access.js
+++ b/lib/handlebars/internal/proto-access.js
@@ -58,7 +58,7 @@ function logUnexpecedPropertyAccessOnce(propertyName) {
       'error',
       `Handlebars: Access has been denied to resolve the property "${propertyName}" because it is not an "own property" of its parent.\n` +
         `You can add a runtime option to disable the check or this warning:\n` +
-        `See http://localhost:8080/api-reference/runtime-options.html#options-to-control-prototype-access for details`
+        `See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details`
     );
   }
 }

From 4cddfe7017c28235ccad98f3434deb3725258da8 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 12 Jan 2020 13:20:37 +0100
Subject: [PATCH 3/4] Update release notes

---
 release-notes.md | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/release-notes.md b/release-notes.md
index ac4fc5041..8e391a775 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -2,7 +2,20 @@
 
 ## Development
 
-[Commits](https://github.com/wycats/handlebars.js/compare/v4.7.0...master)
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.7.1...master)
+
+## v4.7.1 - January 12th, 2020
+
+Bugfixes:
+
+- fix: fix log output in case of illegal property access - f152dfc
+- fix: log error for illegal property access only once per property - 3c1e252
+
+Compatibility notes:
+
+- no incompatibilities are to be expected.
+
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.7.0...v4.7.1)
 
 ## v4.7.0 - January 10th, 2020
 

From 14ba3d0c43d75bcfcdbfb7c95c9fac99d88a17c8 Mon Sep 17 00:00:00 2001
From: Nils Knappmeier <github@knappi.org>
Date: Sun, 12 Jan 2020 13:21:08 +0100
Subject: [PATCH 4/4] v4.7.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 5bb095bc1..ccebdef1b 100644
--- a/components/bower.json
+++ b/components/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.7.0",
+  "version": "4.7.1",
   "main": "handlebars.js",
   "license": "MIT",
   "dependencies": {}
diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec
index 91f7baf80..44747f7f4 100644
--- a/components/handlebars.js.nuspec
+++ b/components/handlebars.js.nuspec
@@ -2,7 +2,7 @@
 <package>
 	<metadata>
 		<id>handlebars.js</id>
-		<version>4.7.0</version>
+		<version>4.7.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 d040cda4f..c296a32c2 100644
--- a/components/package.json
+++ b/components/package.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.7.0",
+  "version": "4.7.1",
   "license": "MIT",
   "jspm": {
     "main": "handlebars",
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index 6e58ad8b4..2aa3a62f5 100644
--- a/lib/handlebars/base.js
+++ b/lib/handlebars/base.js
@@ -5,7 +5,7 @@ import { registerDefaultDecorators } from './decorators';
 import logger from './logger';
 import { resetLoggedProperties } from './internal/proto-access';
 
-export const VERSION = '4.7.0';
+export const VERSION = '4.7.1';
 export const COMPILER_REVISION = 8;
 export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
 
diff --git a/package.json b/package.json
index 62e640504..5c289a2c2 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "handlebars",
   "barename": "handlebars",
-  "version": "4.7.0",
+  "version": "4.7.1",
   "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
   "homepage": "http://www.handlebarsjs.com/",
   "keywords": [
