]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Prevent double plugin registers from losing the list of plugins (#8162)
authorEvert Timberg <evert.timberg+github@gmail.com>
Mon, 14 Dec 2020 10:03:08 +0000 (05:03 -0500)
committerGitHub <noreply@github.com>
Mon, 14 Dec 2020 10:03:08 +0000 (12:03 +0200)
When `Chart.register()` was called twice in a row, the list of
plugin descriptors on the chart instance would be cleared. The
next chart update would then restart all of the plugins, not
knowing that they were already started. In the case of the Legend
and Title, this causes two boxes to appear in the layout system
thus drawing twice.

src/core/core.plugins.js
test/specs/core.plugin.tests.js

index 91e3c61a41d1e1862ff75fe6938ec2a1a07dbb50..5ebd25fa0435b831ec1cf71cfa5b9b18ba0e92e1 100644 (file)
@@ -1,5 +1,6 @@
 import defaults from './core.defaults';
 import registry from './core.registry';
+import {isNullOrUndef} from '../helpers';
 import {callback as callCallback, mergeIf, valueOrDefault} from '../helpers/helpers.core';
 
 /**
@@ -58,8 +59,15 @@ export default class PluginService {
        }
 
        invalidate() {
-               this._oldCache = this._cache;
-               this._cache = undefined;
+               // When plugins are registered, there is the possibility of a double
+               // invalidate situation. In this case, we only want to invalidate once.
+               // If we invalidate multiple times, the `_oldCache` is lost and all of the
+               // plugins are restarted without being correctly stopped.
+               // See https://github.com/chartjs/Chart.js/issues/8147
+               if (!isNullOrUndef(this._cache)) {
+                       this._oldCache = this._cache;
+                       this._cache = undefined;
+               }
        }
 
        /**
index c709846d1e9c7de5e94de6938a55fd6b743ae290..af93dc53af3f5b237c84729b25a7d811c7ebe897 100644 (file)
@@ -342,5 +342,24 @@ describe('Chart.plugins', function() {
 
                        expect(plugin.hook).not.toHaveBeenCalled();
                });
+
+               it('should not restart plugins when a double register occurs', function() {
+                       var results = [];
+                       var chart = window.acquireChart({
+                               plugins: [{
+                                       start: function() {
+                                               results.push(1);
+                                       }
+                               }]
+                       });
+
+                       Chart.register({id: 'abc', hook: function() {}});
+                       Chart.register({id: 'def', hook: function() {}});
+
+                       chart.update();
+
+                       // The plugin on the chart should only be started once
+                       expect(results).toEqual([1]);
+               });
        });
 });