Leaflet.VectorGrid icon indicating copy to clipboard operation
Leaflet.VectorGrid copied to clipboard

Syntax error of Worker code in IE11

Open wyleung opened this issue 8 years ago • 21 comments

Thank you for the great work on this VectorGrid!

It works fine in Webkit based browsers and Edge. However, when I was testing it in IE 11, it was crashing on: https://github.com/Leaflet/Leaflet.VectorGrid/blob/master/src/Leaflet.VectorGrid.Slicer.js#L33

I'd not take any actions yet to debug / rewrite this part of code. Is anyone seeing the same issue ?

wyleung avatar Jan 17 '17 09:01 wyleung

We'll need more information. What is the exact parse error?

By using an instance of Chrome (or Chromium) and using the "sources" tab of the dev console, it's easy to see the code that the worker is running. If you copy-paste that code into a standalone file and load it with IE11, does a (better) error appear?

IvanSanchez avatar Jan 17 '17 09:01 IvanSanchez

Setup:

Leaflet v1.0.2 Leaflet.VectorGrid: https://leaflet.github.io/Leaflet.VectorGrid/dist/Leaflet.VectorGrid.bundled.js Internet Explorer: 11.0.9600.18537

Screenshot:

virtualbox_ie11 - win7_17_01_2017_11_16_28

wyleung avatar Jan 17 '17 10:01 wyleung

Yeah, it's failing to parse the code inside the blob:, but it's not displaying any good information on which line is failing. This will need a bit of extra investigation. :-(

IvanSanchez avatar Jan 17 '17 10:01 IvanSanchez

@IvanSanchez Too bad :( I can spend some time on this issue today..

wyleung avatar Jan 17 '17 10:01 wyleung

I had this same issue at the office, but I can't seem to replicate at home. I think I solved it by adding some polyfills to the head of my HTML like so:

<script src="fetch-ie8/fetch.js"></script>
<script src="es6-promise/dist/es6-promise.js"></script> 

Does that solve your issue? Make sure you grab the latest versions of those polyfills because I think there was some bad code in earlier versions.

You can try my demo and see if you have any issues with the web workers: https://goo.gl/GeavZS

dosstx avatar Jan 17 '17 16:01 dosstx

I am also getting this in IE all version except Edge. Very hard to debugg since its inside the blob. Any news / suggestions on this? The solution by dosstx did not work.

jklongi avatar Mar 08 '17 12:03 jklongi

@jklongi Did you add the function to your code to call the polyfills?

ES6Promise.polyfill();

I'm using IE11 and it works for me....

dosstx avatar Mar 08 '17 12:03 dosstx

I don't think any of the maintainers have IE as a priority, so this would be a good time to step up and submit a PR! We would really appreciate help with this.

perliedman avatar Mar 09 '17 07:03 perliedman

@dosstx Yes I did but it doesn't help. I cant get my code or nor even your example to work. Just facing the same error as @wyleung . I am using browserstack and couple real windows machines to get IE 11 & 10 but not any of them work.

I looked into it and I think the function that gives the worker code __$strToBlobUri is returning the blob in every other browser like so: "blob:http://localhost:8000/fe350922-c073-4d79-af88-cf5c194ccfac" but in IE it returns the blob input as a string but it has been cut off like so:

"data:text/plain; charset=us-ascii,'use strict';

var simplify_1 = simplify$1;

// calculate simplification data using optimized Douglas-Peucker algorithm

function simplify$1(points, tolerance) {

    var sqTolerance = tolerance * tolerance,
        len = points.length,
        first = 0,
        last = len - 1,
        stack = [],
        i, maxSqDist, sqDist, index;

    // always retain the endpoints (1 is the max value)
    points[first][2] = 1;
    points[last][2] = 1;

    // avoid recursion by using a stack
    while (last) {

        maxSqDist = 0;

        for (i = first + 1; i < last; i++) {
            sqDist = getSqSegDist(points[i], points[first], points[last]);

            if (sqDist > maxSqDist) {
                index = i;
                maxSqDist = sqDist;
            }
        }

        if (maxSqDist > sqTolerance) {
            points[index][2] = maxSqDist; // save the point importance in squared pixels as a z coordinate
            stack.push(first);
            stack.push(index);
     "

However the stuff inside that function might be beyond my skill to debugg..

jklongi avatar Mar 09 '17 08:03 jklongi

I was actually able to (kind of) solve this by using the workerCode from version 1.1.0 and calling the worker with this._worker = new Worker(window.URL.createObjectURL(new Blob([workerCode]))); So there is something going on with the forming of new worker code through that __$strToBlobUri function.

jklongi avatar Mar 09 '17 13:03 jklongi

Thanks @IvanSanchez for creating a great Leaflet Plugin. I have the same issue with IE 11 as reported.

Any recommendations for a fix?

msully avatar Apr 18 '17 13:04 msully

@IvanSanchez this may be helpful in understanding the IE 11 issue. A web application that uses the Web Worker blob method may not function in Internet Explorer 11 https://support.microsoft.com/en-us/help/3023851

msully avatar Apr 25 '17 22:04 msully

@msully Hhhhmmm, not very helpful, albeit interesting.

Maybe loading the VectorGrid file with a <script src=... crossorigin='anonymous'> will make something happen?

IvanSanchez avatar Apr 26 '17 07:04 IvanSanchez

@IvanSanchez unfortunately loading the VectorGrid file

Two steps to resolve the IE11 issue:

  1. I remove the variable "workerCode" as a blob URL and moved the worker code into an external file lccWebWorker.js. Then referenced it as var lccworkerCode = './js/lccWebWorker.js';
initialize: function(t, e) {
        L.VectorGrid.prototype.initialize.call(this, e);
        var e = {};
        var lccworkerCode = './js/lccWebWorker.js';
        for (var r in this.options) "rendererFactory" !== r && "vectorTileLayerStyles" !== r && "function" != typeof this.options[r] && (e[r] = this.options[r]);
        this._worker = new Worker(lccworkerCode), this._worker.postMessage(["slice", t, e])
    },
  1. Added IE 11 Promise support: http://stackoverflow.com/questions/36016327/how-to-make-promises-work-in-ie11

A working example : Grass cutting map

msully avatar May 10 '17 07:05 msully

Thanks @msully

For me I changed one line in the L.VectorGrid.Slicer initialize function

From... this._worker = new Worker(workerCode); To... this._worker = new Worker(options.workerCode || workerCode);

Then when creating my layer

L.vectorGrid.slicer(geoJson, {
    workerCode: '/path/to/Leaflet.VectorGrid/WebWorker.js',
    [...]
}).addTo(map);

The code that goes in WebWorker came from var workerCode = __$strToBlobUri("...HERE..."); in the distributed source (just had to replace \n with new line and \" with ")

Harvinator avatar Jul 13 '17 13:07 Harvinator

@Harvinator does VectorGrid still work in Chrome/Firefox etc. after these changes?

If so, would you be able to make a pull request? It's very hard to review the changes you made when just pasting code into a comment. Pull requests are ideal for this.

perliedman avatar Jul 14 '17 11:07 perliedman

@perliedman I've tested in Chrome and it does work yes.

Created pull request https://github.com/Leaflet/Leaflet.VectorGrid/pull/109

(Also edited my above comment to remove all of the worker code I unnecessarily copy/pasted in)

Harvinator avatar Jul 14 '17 12:07 Harvinator

Are there any plans to merge #109 and publish updated version to npm?

protchenkos avatar Jul 26 '18 11:07 protchenkos

Any update on this problem for IE 11? Thanks

2803media avatar Sep 05 '18 09:09 2803media

@Harvinator do you please provide a working example I can't find a way to make it works ! Thanks in advance

2803media avatar Sep 05 '18 17:09 2803media

For those who search a working WebWorker.js here is the gist: https://gist.github.com/2803media/2c2e370fb317311969bd9efcea09e521

The trick is to load the regular script for all browsers except for IE like that:

            `<script type="text/javascript">
	var ua = window.navigator.userAgent;
	var msie = ua.indexOf("MSIE ");

	if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
		document.write('<script type="text/javascript" src="/wp-content/themes/mytheme/js/Leaflet.VectorGrid.bundled.min2.js"><\/script>');
		document.write('<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.js"><\/script>');
		document.write('<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"><\/script>');
	} else {
		document.write('<script type="text/javascript" src="/wp-content/themes/codium-dn/js/Leaflet.VectorGrid.bundled.min.js"><\/script>');
	}
</script>`

Notice the difference for Leaflet.VectorGrid.bundled.min2.js versus Leaflet.VectorGrid.bundled.min.js which is the official one. The gist of Leaflet.VectorGrid.bundled.min2.js is here: https://gist.github.com/2803media/f32ec54340d1d03b44fa0f3609480690

After as @Harvinator said you load the slice like that:

             `if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))  // If Internet Explorer, return version number
					    {
								vectorGrid2 = L.vectorGrid.slicer( geojsonLayer, {
									workerCode: '/wp-content/themes/mytheme/js/WebWorker.js',
									rendererFactory: L.canvas.tile,
									vectorTileLayerStyles: {
										sliced: {
										fillOpacity: 0.1,
										color: 'blue',
										weight: 1,
										stroke: true,
										fill: true,
										}
									},
									interactive: true,
									maxZoom: 19, // max zoom to preserve detail on
									tolerance: 20, // 5 simplification tolerance (higher means simpler)
									extent: 4096, //4096, // 4096 tile extent (both width and height)
									buffer: 64, // 64 default 64tile buffer on each side
									indexMaxZoom: 0, // 0 max zoom in the initial tile index
									indexMaxPoints: 100000, // 100000 max number of points per tile in the index
								}).addTo(map);

							} else {
								vectorGrid2 = L.vectorGrid.slicer( geojsonLayer, {
									rendererFactory: L.canvas.tile,
									vectorTileLayerStyles: {
										sliced: {
										fillOpacity: 0.1,
										color: 'blue',
										weight: 1,
										stroke: true,
										fill: true,
										}
									},
									interactive: true,
									maxZoom: 19, // max zoom to preserve detail on
									tolerance: 20, // 5 simplification tolerance (higher means simpler)
									extent: 4096, //4096, // 4096 tile extent (both width and height)
									buffer: 64, // 64 default 64tile buffer on each side
									indexMaxZoom: 0, // 0 max zoom in the initial tile index
									indexMaxPoints: 100000, // 100000 max number of points per tile in the index
								}).addTo(map);
							}`

2803media avatar Sep 19 '18 13:09 2803media