c3js / c3

:bar_chart: A D3-based reusable chart library
http://c3js.org
MIT License
9.35k stars 1.39k forks source link

[0.7.5+] NS_ERROR_FAILURE on Firefox 47 #2692

Closed boris-petrov closed 5 years ago

boris-petrov commented 5 years ago

Updating from 0.7.4 to any of the two new versions causes NS_ERROR_FAILURE Exception, result: 2147500037. Not sure what that means. This is the stacktrace:

AxisInternal.prototype.updateTickTextCharSize/<@webpack://./node_modules/c3/src/axis-internal.js?:106:15
__webpack_exports__.default@webpack://./node_modules/d3-selection/src/selection/each.js?:5:28
AxisInternal.prototype.updateTickTextCharSize@webpack://./node_modules/c3/src/axis-internal.js?:103:3
axis/<@webpack://./node_modules/c3/src/axis-internal.js?:282:7
__webpack_exports__.default@webpack://./node_modules/d3-selection/src/selection/each.js?:5:28
axis@webpack://./node_modules/c3/src/axis-internal.js?:258:5
__webpack_exports__.default@webpack://./node_modules/d3-selection/src/selection/call.js?:5:3
redraw@webpack://./node_modules/c3/src/axis.js?:480:3
_chart_internal__WEBPACK_IMPORTED_MODULE_0__.ChartInternal.prototype.redraw@webpack://./node_modules/c3/src/core.js?:563:3
_chart_internal__WEBPACK_IMPORTED_MODULE_0__.ChartInternal.prototype.initWithData@webpack://./node_modules/c3/src/core.js?:327:5
_chart_internal__WEBPACK_IMPORTED_MODULE_0__.ChartInternal.prototype.init@webpack://./node_modules/c3/src/core.js?:59:5
Chart@webpack://./node_modules/c3/src/chart.js?:15:3
generate@webpack://./node_modules/c3/src/core.js?:36:12

Using the latest Chrome this doesn't happen so the issue is somewhere with older browsers.

panthony commented 5 years ago

Looks more like something specific to Firefox which raises an NS_ERROR_FAILURE if getBBox is called on an element not displayed (ex: display:none), according to this.

Which is a shame because it was introduced because getBoundingClientRect was returning different values between Chrome & Firefox.

sigh

panthony commented 5 years ago

@boris-petrov Do you have a conf of a graph that triggers the issue ?

I'd like to be sure to have a test case that fails.

Can't seems to reproduce the issue on newer version of Firefox and not sure how I can downgrade to such an old FF version.

boris-petrov commented 5 years ago

@panthony - thanks for the support.

Not sure what you mean by "conf of a graph", could you explain please?

As for using an old Firefox - you can download a distribution from here. Just extract the archive for your OS and run the bin/firefox binary.

Thanks again!

panthony commented 5 years ago

@boris-petrov Not quite sure how to reproduce your issue.

I'm clicking on various samples using firefox 47 and they all seems to show fine.

Can't seems to be able to inspect anything to see if some kind of error shows in a console though...

Not sure what you mean by "conf of a graph", could you explain please?

I'd like to check something that I know for sure trigger the issue. In case this is related to some kind of combinaisons of configurations (ex: legend hidden, missing data point, whatever..).

edit

Found the console, there is a bunch of errors in there that has nothing to do with c3js and I can't seems to find the error you are talking about.

But all charts are displaying fine in sample. Is that really a 'blocking' error or just some error in logs without consequence ?

Firefox 47 starts to be rather old.

boris-petrov commented 5 years ago

The charts don't appear in our case at all due to that error - our integration tests caught that. So it is "blocking", yes.

This FF is very old indeed, we use it to test our ES5 build (and, as you can see, it actually does catch some errors that don't appear in the latest Chrome/Firefox builds). There is pretty much no other browser that you can use to test ES5 on Linux.

I'll try to create some reproduction now or at least give you some pointers.

boris-petrov commented 5 years ago

@panthony - I can see that in my case it breaks when I just call:

const options = {
  bindto: '#someId',
  data: {
    type: 'pie',
    columns: []
  }
};
c3.generate(options);

This doesn't happen on your side using FF 47?

If not, could you point me to some standalone example project using c3 which I can just modify to break?

panthony commented 5 years ago

@boris-petrov Unfortunately no...

Capture d’écran 2019-08-20 à 11 44 33

If there is a different behavior between FF on MacOSX & Linux ...

panthony commented 5 years ago

I'd say you can test the config I used here:

http://jsfiddle.net/xtpcqd30/

But FF47 is able to render jsfiddle apparently.

boris-petrov commented 5 years ago

@panthony - using almost the same code as you, I managed to break it. As you mentioned in your first comment, the div must not be visible:

<h1>chart 1</h1>
<div id="chart1" style="display: none;"></div>

<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.6/c3.min.js"></script>
<script>
  c3.generate({
    bindto: '#chart1',
    data: {
      type: 'pie',
      columns: []
    }
  });
</script>

Note the display: none style.

panthony commented 5 years ago

@boris-petrov Ok, then I believe a quick workaround for you would be to either use, in the mean time, something like visibility:hidden or position:absolute;left-99999px;top:-999999px;.

boris-petrov commented 5 years ago

@panthony - yes, thanks. Will you consider fixing this? It's obviously a horrible Firefox bug but I guess it could be a common use case...

panthony commented 5 years ago

@boris-petrov Ideally yes although I'm not quite sure what could be done instead of try/catch and returning a size of 0.

Before it was using getBoundingClientRect I need to check the return of this method.

boris-petrov commented 5 years ago

You could try-catch, yes, and then fall-back to the old code which used getBoundingClientRect I guess. Best of both worlds.

panthony commented 5 years ago

To be noted that:

A fix could be to wrap getBBox in a try/catch and return an "empty box" in case of an exception.

panthony commented 5 years ago

@boris-petrov Out of curiosity, what do you do once you rendered the chart within a display:none; div ?

Since, as far as I know, the chart can't be rendered properly.

Do you re-call manually redraw or something like this?

boris-petrov commented 5 years ago

@panthony - well, the chart is rendered in a hidden panel, which, when expanded, would make a request and populate the chart with data by calling chart.load(columns: data, unload: true). We could, of course, not call c3.generate(options) at all when not visible. But we wouldn't have caught this bug in that case. :)

Thanks for fixing it so quickly!