Fix parse error for import() in older browsers (#571)

- add import() polyfill that evals in Function() and falls back to script tag injection
- add AbortController polyfill for MapLibre (lazy loaded so can be in bundle, not for Web Workers)
- support Firefox 56, last supporting old plugins before Web Extensions
This commit is contained in:
Norbert Renner 2022-06-28 18:54:21 +02:00
parent c5f841be6c
commit 74a6bcd92e
4 changed files with 107 additions and 61 deletions

View file

@ -5,6 +5,6 @@
"es2021": true "es2021": true
}, },
"settings": { "settings": {
"polyfills": ["URL", "Promise", "navigator", "Uint8Array", "performance", "location.hostname"] "polyfills": ["URL", "Promise", "navigator", "Uint8Array", "performance", "location.hostname", "document.body"]
} }
} }

View file

@ -1,68 +1,102 @@
/** (function () {
* Only load Maplibre bundles when layer is actually added, using dynamic imports // import() uses path relative to calling script, script injection relative to index.html,
*/ // so figure out script-relative path without hard-coding it (only as fallback) for the latter
BR.MaplibreGlLazyLoader = L.Layer.extend({ // eslint-disable-next-line
initialize: function (options) { const baseUrl = document.currentScript?.src.split('/').slice(0, -1).join('/') || window.location.origin + '/dist';
this.options = options; const getAbsoluteScriptUrl = (src) => new URL(src, baseUrl + '/').href;
},
onAdd: function (map) { // simple custom import() polyfill that doesn't need module support and can't load modules
if (!('maplibreGL' in L)) { // (derived from various sources)
this._load(); function importPolyfill(src) {
} else { return new Promise((resolve, reject) => {
this._addGlLayer(); try {
} // `import` is a reserved keyword even in old browsers not supporting it,
return this; // so it needs to be evaluated at runtime, otherwise causes a parse error on load
}, new Function('return import("' + src + '")')().then(() => resolve());
} catch (e) {
onRemove: function (map) { const url = getAbsoluteScriptUrl(src);
this._map.removeLayer(this.glLayer); var script = document.createElement('script');
this.glLayer = null; script.onload = () => {
return this; resolve();
}, };
script.onerror = () => {
// needed when overlay, also requires `position: absolute` (see css) reject(new Error(`Error importing: "${url}"`));
setZIndex: function (zIndex) { script.remove();
this.options.zIndex = zIndex; };
return this; script.src = url;
}, document.body.appendChild(script);
setOpacity: function (opacity) {
if (this.glLayer) {
const glMap = this.glLayer.getMaplibreMap();
if (glMap.getLayer('hillshading')) {
glMap.setPaintProperty('hillshading', 'hillshade-exaggeration', opacity);
} else {
glMap.getCanvas().style.opacity = opacity;
} }
} });
}, }
_load: async function () { /**
await import('./maplibre-gl.js'); * Only load Maplibre bundles when layer is actually added, using dynamic imports
await import('./leaflet-maplibre-gl.js'); */
BR.MaplibreGlLazyLoader = L.Layer.extend({
initialize: function (options) {
this.options = options;
},
this._addGlLayer(); onAdd: function (map) {
}, if (!('maplibreGL' in L)) {
this._load();
} else {
this._addGlLayer();
}
return this;
},
_addGlLayer: function () { onRemove: function (map) {
this.glLayer = L.maplibreGL(this.options); if (this.glLayer) {
// see LayersConfig.createLayer this._map.removeLayer(this.glLayer);
this.glLayer.getAttribution = function () { }
return this.options.mapLink; this.glLayer = null;
}; return this;
this._map.addLayer(this.glLayer); },
this._updateZIndex(); // needed when overlay, also requires `position: absolute` (see css)
}, setZIndex: function (zIndex) {
this.options.zIndex = zIndex;
return this;
},
_updateZIndex: function () { setOpacity: function (opacity) {
if (this.glLayer && this.glLayer.getContainer() && this.options.zIndex != null) { if (this.glLayer) {
this.glLayer.getContainer().style.zIndex = this.options.zIndex; const glMap = this.glLayer.getMaplibreMap();
} if (glMap.getLayer('hillshading')) {
}, glMap.setPaintProperty('hillshading', 'hillshade-exaggeration', opacity);
}); } else {
glMap.getCanvas().style.opacity = opacity;
}
}
},
BR.maplibreGlLazyLoader = function (options) { _load: async function () {
return new BR.MaplibreGlLazyLoader(options); await importPolyfill('./maplibre-gl.js');
}; await importPolyfill('./leaflet-maplibre-gl.js');
this._addGlLayer();
},
_addGlLayer: function () {
this.glLayer = L.maplibreGL(this.options);
// see LayersConfig.createLayer
this.glLayer.getAttribution = function () {
return this.options.mapLink;
};
this._map.addLayer(this.glLayer);
this._updateZIndex();
},
_updateZIndex: function () {
if (this.glLayer && this.glLayer.getContainer() && this.options.zIndex != null) {
this.glLayer.getContainer().style.zIndex = this.options.zIndex;
}
},
});
BR.maplibreGlLazyLoader = function (options) {
return new BR.MaplibreGlLazyLoader(options);
};
})();

View file

@ -28,6 +28,7 @@
"> 0.5%", "> 0.5%",
"last 2 versions", "last 2 versions",
"Firefox ESR", "Firefox ESR",
"Firefox >= 56",
"not dead", "not dead",
"Explorer >= 10", "Explorer >= 10",
"Android >= 4.1", "Android >= 4.1",
@ -44,6 +45,7 @@
"@maplibre/maplibre-gl-leaflet": "^0.0.17", "@maplibre/maplibre-gl-leaflet": "^0.0.17",
"@turf/turf": "^6.2.0", "@turf/turf": "^6.2.0",
"Leaflet.vector-markers": "nrenner/Leaflet.vector-markers#2ef80c9", "Leaflet.vector-markers": "nrenner/Leaflet.vector-markers#2ef80c9",
"abortcontroller-polyfill": "^1.7.3",
"async": "~2.6.0", "async": "~2.6.0",
"bootbox": "~5.5.2", "bootbox": "~5.5.2",
"bootstrap": "4.6.1", "bootstrap": "4.6.1",
@ -380,6 +382,11 @@
"dist/maplibre-gl.js.map", "dist/maplibre-gl.js.map",
"dist/maplibre-gl.css" "dist/maplibre-gl.css"
] ]
},
"abortcontroller-polyfill": {
"main": [
"dist/polyfill-patch-fetch.js"
]
} }
} }
} }

View file

@ -3418,6 +3418,11 @@ abbrev@1:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
abortcontroller-polyfill@^1.7.3:
version "1.7.3"
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.3.tgz#1b5b487bd6436b5b764fd52a612509702c3144b5"
integrity sha512-zetDJxd89y3X99Kvo4qFx8GKlt6GsvN3UcRZHwU6iFA/0KiOmhkTVhe8oRoTBiTVPZu09x3vCra47+w8Yz1+2Q==
accepts@~1.3.4: accepts@~1.3.4:
version "1.3.7" version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"