Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

interval.range should protect against infinite loops. #25

Closed
BrunoRB opened this issue Jul 18, 2017 · 9 comments
Closed

interval.range should protect against infinite loops. #25

BrunoRB opened this issue Jul 18, 2017 · 9 comments

Comments

@BrunoRB
Copy link

BrunoRB commented Jul 18, 2017

d3.timeWeek.range(new Date(2017, 6, 10), new Date(2017, 9, 10));

The code above works fine on chrome, but creates an infinite loop on firefox (-v 52.2.0, tested on two different linux machines).
Doing some debugging I ended up here, the do-while never halts. Placing some console.log calls in the code I got the following:

do {
	range.push(new Date(+start));
	if (_dbgstop++ >= 100) {
		throw 'stop';
	}
	console.log(start.toISOString());
	offseti(start, step);
	console.log(start.toISOString());
	floori(start);
	console.log(start.toISOString());
	console.log(stop, start < stop);
} while (start < stop);

firefox:

 d3.timeWeek.range(
    new Date(2017, 6, 10),
    new Date(2017, 9, 10)
);
2017-07-16T03:00:00.000Z  d3-time.js:45:3
2017-07-23T03:00:00.000Z  d3-time.js:47:3
2017-07-23T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-07-23T03:00:00.000Z  d3-time.js:45:3
2017-07-30T03:00:00.000Z  d3-time.js:47:3
2017-07-30T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-07-30T03:00:00.000Z  d3-time.js:45:3
2017-08-06T03:00:00.000Z  d3-time.js:47:3
2017-08-06T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-08-06T03:00:00.000Z  d3-time.js:45:3
2017-08-13T03:00:00.000Z  d3-time.js:47:3
2017-08-13T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-08-13T03:00:00.000Z  d3-time.js:45:3
2017-08-20T03:00:00.000Z  d3-time.js:47:3
2017-08-20T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-08-20T03:00:00.000Z  d3-time.js:45:3
2017-08-27T03:00:00.000Z  d3-time.js:47:3
2017-08-27T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-08-27T03:00:00.000Z  d3-time.js:45:3
2017-09-03T03:00:00.000Z  d3-time.js:47:3
2017-09-03T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-09-03T03:00:00.000Z  d3-time.js:45:3
2017-09-10T03:00:00.000Z  d3-time.js:47:3
2017-09-10T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-09-10T03:00:00.000Z  d3-time.js:45:3
2017-09-17T03:00:00.000Z  d3-time.js:47:3
2017-09-17T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-09-17T03:00:00.000Z  d3-time.js:45:3
2017-09-24T03:00:00.000Z  d3-time.js:47:3
2017-09-24T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-09-24T03:00:00.000Z  d3-time.js:45:3
2017-10-01T03:00:00.000Z  d3-time.js:47:3
2017-10-01T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-10-01T03:00:00.000Z  d3-time.js:45:3
2017-10-08T03:00:00.000Z  d3-time.js:47:3
2017-10-08T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-10-08T03:00:00.000Z  d3-time.js:45:3
2017-10-15T02:00:00.000Z  d3-time.js:47:3
2017-10-08T03:00:00.000Z  d3-time.js:49:3
Date 2017-10-10T03:00:00.000Z true  d3-time.js:50:3
2017-10-08T03:00:00.000Z  d3-time.js:45:3
2017-10-15T02:00:00.000Z  d3-time.js:47:3
2017-10-08T03:00:00.000Z
.... (more of the same)
Error: stop

so offseti increases 2017-10-08T03:00:00.000Z to 2017-10-15T02:00:00.000Z and then floori decreases it back to 2017-10-08T03:00:00.000Z and this keeps going on forever.

for chrome we have:

(sameas ff)...
2017-09-24T03:00:00.000Z
d3-time.js:47 2017-10-01T03:00:00.000Z
d3-time.js:49 2017-10-01T03:00:00.000Z
d3-time.js:50 Tue Oct 10 2017 00:00:00 GMT-0300 (-03) true
d3-time.js:45 2017-10-01T03:00:00.000Z
d3-time.js:47 2017-10-08T03:00:00.000Z
d3-time.js:49 2017-10-08T03:00:00.000Z
d3-time.js:50 Tue Oct 10 2017 00:00:00 GMT-0300 (-03) true
d3-time.js:45 2017-10-08T03:00:00.000Z
d3-time.js:47 2017-10-15T03:00:00.000Z
d3-time.js:49 2017-10-15T03:00:00.000Z
d3-time.js:50 Tue Oct 10 2017 00:00:00 GMT-0300 (-03) false
@mbostock
Copy link
Member

A reduction of this issue (requires switching to Brasilia Standard Time):

date = new Date("2017-10-08T03:00:00.000Z") // Date 2017-10-08T03:00:00.000Z
d3.timeWeek(date) // Date 2017-10-08T03:00:00.000Z
d3.timeWeek.offset(date, 1) // Date 2017-10-15T02:00:00.000Z
d3.timeWeek(d3.timeWeek.offset(date, 1)) // Date 2017-10-08T03:00:00.000Z

@mbostock
Copy link
Member

Actually, it’s even worse in that d3.timeWeek is not idempotent:

date = new Date("2017-10-15T03:00:00.000Z") // Date 2017-10-15T03:00:00.000Z
d3.timeWeek(date) // Date 2017-10-15T02:00:00.000Z
d3.timeWeek(d3.timeWeek(date)) // Date 2017-10-08T03:00:00.000Z

@mbostock
Copy link
Member

mbostock commented Jul 31, 2017

In vanilla JavaScript (Firefox):

date = new Date("2017-10-15T03:00:00.000Z") // Date 2017-10-15T03:00:00.000Z
date.setHours(0, 0, 0, 0) // Date 2017-10-15T02:00:00.000Z
date.setHours(0, 0, 0, 0) // Date 2017-10-14T03:00:00.000Z

Whereas in Chrome:

date = new Date("2017-10-15T03:00:00.000Z") // Date 2017-10-15T03:00:00.000Z
date.setHours(0, 0, 0, 0) // Date 2017-10-15T03:00:00.000Z
date.setHours(0, 0, 0, 0) // Date 2017-10-15T03:00:00.000Z

So in other words, calling date.setHours in Firefox is changing the date from the 15th to the 14th.

@mbostock
Copy link
Member

(d3.timeDay is also not idempotent in Firefox, for the same reasons.)

@mbostock
Copy link
Member

mbostock commented Jul 31, 2017

I’m not sure it’s feasible to return the correct result in Firefox; in general, D3 is not a compatibility layer, so I rarely try to workaround a bug in date.setHours (and I think this counts as a bug… although perhaps I am misreading the spec). That said, if there’s a reasonably simple workaround, I’d be amenable to using it—I just can’t think of one immediately.

I’d also like to guarantee that interval.range can’t go into an infinite loop, but I think that would still mean that Firefox would have incorrect results. I’ll change this issue title accordingly.

@mbostock mbostock changed the title timeWeek.range creates an infinite loop in firefox interval.range should protect against infinite loops. Jul 31, 2017
@brunobg
Copy link

brunobg commented Oct 10, 2017

Any plans to make a new release soon with this patch?

@mbostock
Copy link
Member

Thanks for the reminder. Will try to do this soon…

@martgnz
Copy link
Contributor

martgnz commented Nov 21, 2017

Is there any update on this? We are blocked on releasing a project as this is still a problem with Firefox 57. Thank you!

@mbostock
Copy link
Member

Will try today. Thanks for the reminder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants