Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScriptCore.framework Objective-C API introduced with IOS 7 gives a bad NSDate conversion (BUG?)

I'm embedding Javascript into my IOS 7 app via the new JavaScriptCore.framework Objective-C API introduced with IOS 7.

For those looking for an intro to this well-integrated bridge between Objective-C and Javascript, check out the WWDC introduction "Integrating JavaScript into Native Apps" session on Apple's developer network: https://developer.apple.com/wwdc/videos/?id=615.

EDIT: WWDC 2013's video collection has now moved here: https://developer.apple.com/videos/wwdc/2013/?id=615

The problem I have is my NSDate objects (both passed args and directly set Javascript variables) seem to be badly converted to Javascript dates. Here's my code:

self.javascriptContext[@"consoleLog"] = ^(NSString *message) {
    NSLog(@"Javascript log: %@",message);
};
NSDate *myDate = [NSDate date];
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:@"EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ"]; // Show in same format as javascript
NSLog(@"myDate = %@", [dateFormatter stringFromDate:myDate]);
self.javascriptContext[@"date1"] = myDate;
[self.javascriptContext evaluateScript:@"var myDateFn = function(dateArg) { consoleLog(\"date1 = \" + date1); consoleLog(\"dateArg = \" + dateArg); return dateArg };"];
JSValue *function = self.javascriptContext[@"myDateFn"];
NSArray *argList = [NSArray arrayWithObjects:myDate, nil];
JSValue *result = [function callWithArguments:argList];
NSDate *javascriptDate = [result toDate];
NSLog(@"javascriptDate = %@", [dateFormatter stringFromDate:javascriptDate]);

Which produces the following log:

2014-01-24 14:42:08.019 yhere[70180:70b] myDate = Fri Jan 24 2014 14:42:08 GMT+1100
2014-01-24 14:42:08.019 yhere[70180:70b] Javascript log: date1 = Sat Jan 17 1970 13:15:34 GMT+1100 (EST)
2014-01-24 14:42:08.020 yhere[70180:70b] Javascript log: dateArg = Sat Jan 17 1970 13:15:34 GMT+1100 (EST)
2014-01-24 14:42:08.020 yhere[70180:70b] javascriptDate = Fri Jan 24 2014 14:42:08 GMT+1100

Note the dates are different inside Javascript. I've checked - there are no exceptions or other errors occurring inside the Javascript code (I didn't include the exception handling here for clarity).

Please check if I've done something stupid, otherwise it seems to me that there is a bug in the JavaScriptCore.framework

It's almost as if the framework forgot to allow for the fact that Javascript dates are measured in milliseconds since 1970 rather than seconds since 1970 as used by [NSDate dateWithTimeIntervalSince1970:]

If I force a date 1000x bigger before passing to Javascript and divide by 1000 on exit (see code below) then all the dates are correct (i.e. the same date) in the log:

NSDate *myDate = [NSDate date];
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:@"EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ"]; // Show in same format as javascript
NSLog(@"myDate = %@", [dateFormatter stringFromDate:myDate]);
myDate = [NSDate dateWithTimeIntervalSince1970:[myDate timeIntervalSince1970]*1000]; // Workaround BUG
self.javascriptContext[@"date1"] = myDate;
[self.javascriptContext evaluateScript:@"var myDateFn = function(dateArg) { consoleLog(\"date1 = \" + date1); consoleLog(\"dateArg = \" + dateArg); return dateArg };"];
JSValue *function = self.javascriptContext[@"myDateFn"];
NSArray *argList = [NSArray arrayWithObjects:myDate, nil];
JSValue *result = [function callWithArguments:argList];
NSDate *javascriptDate = [result toDate];
javascriptDate = [NSDate dateWithTimeIntervalSince1970:[javascriptDate timeIntervalSince1970]/1000]; // Workaround BUG
NSLog(@"javascriptDate = %@", [dateFormatter stringFromDate:javascriptDate]);

Updated log:

2014-01-24 14:43:44.156 yhere[70180:70b] myDate = Fri Jan 24 2014 14:43:44 GMT+1100
2014-01-24 14:43:44.157 yhere[70180:70b] Javascript log: date1 = Fri Jan 24 2014 14:43:44 GMT+1100 (EST)
2014-01-24 14:43:44.157 yhere[70180:70b] Javascript log: dateArg = Fri Jan 24 2014 14:43:44 GMT+1100 (EST)
2014-01-24 14:43:44.158 yhere[70180:70b] javascriptDate = Fri Jan 24 2014 14:43:44 GMT+1100

I have raised a bug report for this (15920754). Does anyone think this is not a bug and I have done something wrong?

like image 346
Mike Avatar asked Jan 24 '14 04:01

Mike


1 Answers

I'm going to flag this question as closed since I have raised a bug report with Apple for this issue (15920754) - the multiply by 1000 prior to Javascript conversion and the divide by 1000 after conversion back from Javascript to get the right values makes it pretty obvious that Apple has a bug here.

I'll re-post if Apple says otherwise when I hear from them.

UPDATE:

Apple have corrected this issue in iOS 8

like image 181
Mike Avatar answered Oct 13 '22 19:10

Mike