123 lines
3.7 KiB
JavaScript
123 lines
3.7 KiB
JavaScript
'use strict';
|
|
|
|
exports.supported = isSupported;
|
|
exports.notSupportedReason = notSupportedReason;
|
|
|
|
/**
|
|
* Test whether the current browser supports Mapbox GL JS
|
|
* @param {Object} options
|
|
* @param {boolean} [options.failIfMajorPerformanceCaveat=false] Return `false`
|
|
* if the performance of Mapbox GL JS would be dramatically worse than
|
|
* expected (i.e. a software renderer is would be used)
|
|
* @return {boolean}
|
|
*/
|
|
function isSupported(options) {
|
|
return !notSupportedReason(options);
|
|
}
|
|
|
|
function notSupportedReason(options) {
|
|
if (!isBrowser()) return 'not a browser';
|
|
if (!isWorkerSupported()) return 'insufficient worker support';
|
|
if (!isCanvasGetImageDataSupported()) return 'insufficient Canvas/getImageData support';
|
|
if (!isWebGLSupportedCached(options && options.failIfMajorPerformanceCaveat)) return 'insufficient WebGL2 support';
|
|
if (!isNotIE()) return 'insufficient ECMAScript 6 support';
|
|
}
|
|
|
|
function isBrowser() {
|
|
return typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
}
|
|
|
|
function isWorkerSupported() {
|
|
if (!('Worker' in window && 'Blob' in window && 'URL' in window)) {
|
|
return false;
|
|
}
|
|
|
|
var blob = new Blob([''], { type: 'text/javascript' });
|
|
var workerURL = URL.createObjectURL(blob);
|
|
var supported;
|
|
var worker;
|
|
|
|
try {
|
|
worker = new Worker(workerURL);
|
|
supported = true;
|
|
} catch (e) {
|
|
supported = false;
|
|
}
|
|
|
|
if (worker) {
|
|
worker.terminate();
|
|
}
|
|
URL.revokeObjectURL(workerURL);
|
|
|
|
return supported;
|
|
}
|
|
|
|
// Some browsers or browser extensions block access to canvas data to prevent fingerprinting.
|
|
// Mapbox GL uses this API to load sprites and images in general.
|
|
function isCanvasGetImageDataSupported() {
|
|
var canvas = document.createElement('canvas');
|
|
canvas.width = canvas.height = 1;
|
|
var context = canvas.getContext('2d');
|
|
if (!context) {
|
|
return false;
|
|
}
|
|
var imageData = context.getImageData(0, 0, 1, 1);
|
|
return imageData && imageData.width === canvas.width;
|
|
}
|
|
|
|
var isWebGLSupportedCache = {};
|
|
function isWebGLSupportedCached(failIfMajorPerformanceCaveat) {
|
|
|
|
if (isWebGLSupportedCache[failIfMajorPerformanceCaveat] === undefined) {
|
|
isWebGLSupportedCache[failIfMajorPerformanceCaveat] = isWebGLSupported(failIfMajorPerformanceCaveat);
|
|
}
|
|
|
|
return isWebGLSupportedCache[failIfMajorPerformanceCaveat];
|
|
}
|
|
|
|
isSupported.webGLContextAttributes = {
|
|
antialias: false,
|
|
alpha: true,
|
|
stencil: true,
|
|
depth: true
|
|
};
|
|
|
|
function getWebGLContext(failIfMajorPerformanceCaveat) {
|
|
var canvas = document.createElement('canvas');
|
|
|
|
var attributes = Object.create(isSupported.webGLContextAttributes);
|
|
attributes.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat;
|
|
|
|
return canvas.getContext('webgl2', attributes);
|
|
}
|
|
|
|
function isWebGLSupported(failIfMajorPerformanceCaveat) {
|
|
var gl = getWebGLContext(failIfMajorPerformanceCaveat);
|
|
if (!gl) {
|
|
return false;
|
|
}
|
|
|
|
// Try compiling a shader and get its compile status. Some browsers like Brave block this API
|
|
// to prevent fingerprinting. Unfortunately, this also means that Mapbox GL won't work.
|
|
var shader;
|
|
try {
|
|
shader = gl.createShader(gl.VERTEX_SHADER);
|
|
} catch (e) {
|
|
// some older browsers throw an exception that `createShader` is not defined
|
|
// so handle this separately from the case where browsers block `createShader`
|
|
// for security reasons
|
|
return false;
|
|
}
|
|
|
|
if (!shader || gl.isContextLost()) {
|
|
return false;
|
|
}
|
|
gl.shaderSource(shader, 'void main() {}');
|
|
gl.compileShader(shader);
|
|
return gl.getShaderParameter(shader, gl.COMPILE_STATUS) === true;
|
|
}
|
|
|
|
function isNotIE() {
|
|
return !document.documentMode;
|
|
}
|