Fix failing instanceof when reading context

`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`.
This commit is contained in:
Simon Brunel 2017-04-22 09:49:10 +02:00 committed by Evert Timberg
parent f2c569ef25
commit f7d2d7536a
3 changed files with 39 additions and 11 deletions

View File

@ -196,16 +196,22 @@ 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) {
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;
},

View 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';

View 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() {