]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fix failing instanceof when reading context
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Sat, 22 Apr 2017 07:49:10 +0000 (09:49 +0200)
committerEvert Timberg <evert.timberg+github@gmail.com>
Sat, 22 Apr 2017 17:14:16 +0000 (13:14 -0400)
`instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is inside an iframe or when running in a protected environment. We could guess the types from their toString() value but let's keep things flexible and assume it's a sufficient condition if the item has a context2D which has item as `canvas`.

src/platforms/platform.dom.js
test/jasmine.matchers.js
test/specs/platform.dom.tests.js

index 317d4bfed73ad8432b285ab5e704ec9243454e4a..524bc346e37048df4ef47e56bd477c70c9ed8a1d 100644 (file)
@@ -196,15 +196,21 @@ module.exports = function(Chart) {
                                item = item.canvas;
                        }
 
-                       if (item instanceof HTMLCanvasElement) {
-                               // To prevent canvas fingerprinting, some add-ons undefine the getContext
-                               // method, for example: https://github.com/kkapsner/CanvasBlocker
-                               // https://github.com/chartjs/Chart.js/issues/2807
-                               var context = item.getContext && item.getContext('2d');
-                               if (context instanceof CanvasRenderingContext2D) {
-                                       initCanvas(item, config);
-                                       return context;
-                               }
+                       // To prevent canvas fingerprinting, some add-ons undefine the getContext
+                       // method, for example: https://github.com/kkapsner/CanvasBlocker
+                       // https://github.com/chartjs/Chart.js/issues/2807
+                       var context = item && item.getContext && item.getContext('2d');
+
+                       // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is
+                       // inside an iframe or when running in a protected environment. We could guess the
+                       // types from their toString() value but let's keep things flexible and assume it's
+                       // a sufficient condition if the item has a context2D which has item as `canvas`.
+                       // https://github.com/chartjs/Chart.js/issues/3887
+                       // https://github.com/chartjs/Chart.js/issues/4102
+                       // https://github.com/chartjs/Chart.js/issues/4152
+                       if (context && context.canvas === item) {
+                               initCanvas(item, config);
+                               return context;
                        }
 
                        return null;
index 8a3c9e121a3cee7d0fa36eb7892db2b240d8957e..832fba35ecf21d1bab27740bbe648d25f203d078 100644 (file)
@@ -93,9 +93,9 @@ function toBeValidChart() {
 
                        if (!(actual instanceof Chart)) {
                                message = 'Expected ' + actual + ' to be an instance of Chart';
-                       } else if (!(actual.canvas instanceof HTMLCanvasElement)) {
+                       } else if (Object.prototype.toString.call(actual.canvas) !== '[object HTMLCanvasElement]') {
                                message = 'Expected canvas to be an instance of HTMLCanvasElement';
-                       } else if (!(actual.ctx instanceof CanvasRenderingContext2D)) {
+                       } else if (Object.prototype.toString.call(actual.ctx) !== '[object CanvasRenderingContext2D]') {
                                message = 'Expected context to be an instance of CanvasRenderingContext2D';
                        } else if (typeof actual.height !== 'number' || !isFinite(actual.height)) {
                                message = 'Expected height to be a strict finite number';
index 898de9c4842373486ab840bc6c472f9fb3bbaf1b..7ca768307e1b810298a7ea35b1ae2a89b4667917 100644 (file)
@@ -79,6 +79,28 @@ describe('Platform.dom', function() {
 
                        chart.destroy();
                });
+
+               it('should accept a canvas from an iframe', function(done) {
+                       var iframe = document.createElement('iframe');
+                       iframe.onload = function() {
+                               var doc = iframe.contentDocument;
+                               doc.body.innerHTML += '<canvas id="chart"></canvas>';
+                               var canvas = doc.getElementById('chart');
+                               var chart = new Chart(canvas);
+
+                               expect(chart).toBeValidChart();
+                               expect(chart.canvas).toBe(canvas);
+                               expect(chart.ctx).toBe(canvas.getContext('2d'));
+
+                               chart.destroy();
+                               canvas.remove();
+                               iframe.remove();
+
+                               done();
+                       };
+
+                       document.body.appendChild(iframe);
+               });
        });
 
        describe('config.options.aspectRatio', function() {