From 2453e403efc7ae25920e36c3e73049ce2773973c Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 29 Apr 2010 12:04:44 -0700 Subject: [PATCH 1/9] Make nil a completely valid object in a CPArray. Closes #630. --- Foundation/CPArray.j | 50 ++++++++++++---------------------- Tests/Foundation/CPArrayTest.j | 29 ++++++++++---------- 2 files changed, 31 insertions(+), 48 deletions(-) diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index ab149a6fb..e26731db4 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -145,10 +145,10 @@ { var i = 2, array = [[self alloc] init], - argument; + count = arguments.length; - for (; i < arguments.length && (argument = arguments[i]) != nil; ++i) - array.push(argument); + for (; i < count; ++i) + array.push(arguments[i]); return array; } @@ -229,10 +229,10 @@ { // The arguments array contains self and _cmd, so the first object is at position 2. var i = 2, - argument; + count = arguments.length; - for (; i < arguments.length && (argument = arguments[i]) != nil; ++i) - push(argument); + for (; i < count; ++i) + push(arguments[i]); return self; } @@ -278,21 +278,18 @@ /*! Returns the index of \c anObject in this array. - If the object is \c nil or not in the array, + If the object is not in the array, returns \c CPNotFound. It first attempts to find - a match using \c -isEqual:, then \c ==. + a match using \c -isEqual:, then \c ===. @param anObject the object to search for */ - (int)indexOfObject:(id)anObject { - if (anObject === nil) - return CPNotFound; - var i = 0, count = length; // Only use -isEqual: if our object is a CPObject. - if (anObject.isa) + if (anObject && anObject.isa) { for (; i < count; ++i) if ([self[i] isEqual:anObject]) @@ -305,7 +302,7 @@ // Last resort, do a straight forward linear O(N) search. else for (; i < count; ++i) - if (self[i] == anObject) + if (self[i] === anObject) return i; return CPNotFound; @@ -314,21 +311,18 @@ /*! Returns the index of \c anObject in the array within \c aRange. It first attempts to find - a match using \c -isEqual:, then \c ==. + a match using \c -isEqual:, then \c ===. @param anObject the object to search for @param aRange the range to search within @return the index of the object, or \c CPNotFound if it was not found. */ - (int)indexOfObject:(id)anObject inRange:(CPRange)aRange { - if (anObject === nil) - return CPNotFound; - var i = aRange.location, count = MIN(CPMaxRange(aRange), length); // Only use isEqual: if our object is a CPObject. - if (anObject.isa) + if (anObject && anObject.isa) { for (; i < count; ++i) if ([self[i] isEqual:anObject]) @@ -337,22 +331,19 @@ // Last resort, do a straight forward linear O(N) search. else for (; i < count; ++i) - if (self[i] == anObject) + if (self[i] === anObject) return i; return CPNotFound; } /*! - Returns the index of \c anObject in the array. The test for equality is done using only \c ==. + Returns the index of \c anObject in the array. The test for equality is done using only \c ===. @param anObject the object to search for @return the index of the object in the array. \c CPNotFound if the object is not in the array. */ - (int)indexOfObjectIdenticalTo:(id)anObject { - if (anObject === nil) - return CPNotFound; - // If indexOf exists, use it since it's probably // faster than anything we can implement. if (self.indexOf) @@ -382,9 +373,6 @@ */ - (int)indexOfObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange { - if (anObject === nil) - return CPNotFound; - // If indexOf exists, use it since it's probably // faster than anything we can implement. if (self.indexOf) @@ -460,7 +448,7 @@ - (unsigned)_indexOfObject:(id)anObject sortedByFunction:(Function)aFunction context:(id)aContext { - if (!aFunction || anObject === undefined) + if (!aFunction) return CPNotFound; if (length === 0) @@ -523,7 +511,8 @@ { var count = [self count]; - if (!count) return nil; + if (!count) + return nil; return self[count - 1]; } @@ -697,12 +686,7 @@ */ - (CPArray)arrayByAddingObject:(id)anObject { - if (anObject === nil || anObject === undefined) - [CPException raise:CPInvalidArgumentException - reason:"arrayByAddingObject: object can't be nil"]; - var array = [self copy]; - array.push(anObject); return array; diff --git a/Tests/Foundation/CPArrayTest.j b/Tests/Foundation/CPArrayTest.j index f99ec7b78..75cc9cf01 100644 --- a/Tests/Foundation/CPArrayTest.j +++ b/Tests/Foundation/CPArrayTest.j @@ -21,8 +21,8 @@ - (void)testsInsertObjectsAtIndexes { - var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four", nil], - newAdditions = [CPArray arrayWithObjects:@"a", @"b", nil], + var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four"], + newAdditions = [CPArray arrayWithObjects:@"a", @"b"], indexes = [CPMutableIndexSet indexSetWithIndex:1]; [indexes addIndex:3]; @@ -31,8 +31,8 @@ [self assert:array equals:[@"one", @"a", @"two", @"b", @"three", @"four"]]; - var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four", nil], - newAdditions = [CPArray arrayWithObjects:@"a", @"b", nil], + var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four"], + newAdditions = [CPArray arrayWithObjects:@"a", @"b"], indexes = [CPMutableIndexSet indexSetWithIndex:5]; [indexes addIndex:4]; @@ -41,8 +41,8 @@ [self assert:array equals:[@"one", @"two", @"three", @"four", @"a", @"b"]]; - var array = [CPMutableArray arrayWithObjects: @"one", @"two", @"three", @"four", nil], - newAdditions = [CPArray arrayWithObjects: @"a", @"b", @"c", nil], + var array = [CPMutableArray arrayWithObjects: @"one", @"two", @"three", @"four"], + newAdditions = [CPArray arrayWithObjects: @"a", @"b", @"c"], indexes = [CPMutableIndexSet indexSetWithIndex:1]; [indexes addIndex:2]; @@ -53,8 +53,8 @@ [self assert:array equals:[@"one", @"a", @"b", @"two", @"c", @"three", @"four"]]; - var array = [CPMutableArray arrayWithObjects: @"one", @"two", @"three", @"four", nil], - newAdditions = [CPArray arrayWithObjects: @"a", @"b", @"c", nil], + var array = [CPMutableArray arrayWithObjects: @"one", @"two", @"three", @"four"], + newAdditions = [CPArray arrayWithObjects: @"a", @"b", @"c"], indexes = [CPMutableIndexSet indexSetWithIndex:1]; [indexes addIndex:2]; @@ -64,10 +64,9 @@ [self assert:array equals:[@"one", @"a", @"b", @"two", @"three", @"four", @"c"]]; - // - - var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four", nil], - newAdditions = [CPArray arrayWithObjects:@"a", @"b", nil], + + var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four"], + newAdditions = [CPArray arrayWithObjects:@"a", @"b"], indexes = [CPMutableIndexSet indexSetWithIndex:5]; [indexes addIndex:6]; @@ -88,10 +87,10 @@ { var array = [CPMutableArray arrayWithObjects:@"one", @"two", @"three", @"four", nil], indexes = [CPMutableIndexSet indexSetWithIndex: 2]; - + [array removeObjectsAtIndexes: indexes]; - - [self assert:array equals:[@"one", @"two", @"four"]]; + + [self assert:array equals:[@"one", @"two", @"four", nil]]; } - (void)testIndexOfObjectSortedByFunction From 1545f7b60afea3e08d8afe67f6fb9411c6f4f679 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 29 Apr 2010 15:38:33 -0700 Subject: [PATCH 2/9] Return the cib created in CibLoading.j methods. --- AppKit/Cib/CPCibLoading.j | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/AppKit/Cib/CPCibLoading.j b/AppKit/Cib/CPCibLoading.j index aa7007556..22543eddc 100644 --- a/AppKit/Cib/CPCibLoading.j +++ b/AppKit/Cib/CPCibLoading.j @@ -37,12 +37,12 @@ var CPCibOwner = @"CPCibOwner"; @implementation CPBundle (CPCibLoading) -+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable ++ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable { - [[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable]; + return [[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable]; } -+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner ++ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner { if (![aName hasSuffix:@".cib"]) aName = [aName stringByAppendingString:@".cib"]; @@ -51,24 +51,24 @@ var CPCibOwner = @"CPCibOwner"; var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle], path = [bundle pathForResource:aName]; - [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]]; + return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]]; } -- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable +- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable { - [[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable]; + return [[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable]; } -+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate ++ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate { - [[CPCib alloc] + return ([[CPCib alloc] initWithContentsOfURL:anAbsolutePath loadDelegate:[[_CPCibLoadDelegate alloc] initWithLoadDelegate:aDelegate - externalNameTable:aNameTable]]; + externalNameTable:aNameTable]]); } -+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate ++ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate { if (![aName hasSuffix:@".cib"]) aName = [aName stringByAppendingString:@".cib"]; @@ -77,17 +77,17 @@ var CPCibOwner = @"CPCibOwner"; var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle], path = [bundle pathForResource:aName]; - [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate]; + return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate]; } -- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate +- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate { - [[CPCib alloc] + return ([[CPCib alloc] initWithCibNamed:aFileName bundle:self loadDelegate:[[_CPCibLoadDelegate alloc] initWithLoadDelegate:aDelegate - externalNameTable:aNameTable]]; + externalNameTable:aNameTable]]); } @end From f98d3bd44bfcaa322e9f1501ebc6b87dbb3043ad Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sat, 1 May 2010 11:57:32 -0700 Subject: [PATCH 3/9] Add global 403 handler for CFHTTPRequest, to make it easier to catch authentication challenges. --- Objective-J/CFHTTPRequest.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Objective-J/CFHTTPRequest.js b/Objective-J/CFHTTPRequest.js index d4f9cba76..f44b334db 100644 --- a/Objective-J/CFHTTPRequest.js +++ b/Objective-J/CFHTTPRequest.js @@ -101,6 +101,9 @@ GLOBAL(CFHTTPRequest) = function() { determineAndDispatchHTTPRequestEvents(self); } + + if (CFHTTPRequest.AuthenticationDelegate !== nil) + this._eventDispatcher.addEventListener("HTTP403", function(){CFHTTPRequest.AuthenticationDelegate(self)}); } CFHTTPRequest.UninitializedState = 0; @@ -109,6 +112,9 @@ CFHTTPRequest.LoadedState = 2; CFHTTPRequest.InteractiveState = 3; CFHTTPRequest.CompleteState = 4; +//override to forward all CFHTTPRequest authorization failures to a single function +CFHTTPRequest.AuthenticationDelegate = nil; + CFHTTPRequest.prototype.status = function() { try From 09727909b34f67a4c1c2cf36f728dbba4b600c62 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sat, 1 May 2010 14:47:43 -0700 Subject: [PATCH 4/9] Fix for menuless windows. Closes #640. --- AppKit/CPWindow/CPWindow.j | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 209f6e769..f06953ab1 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -1933,7 +1933,8 @@ CPTexturedBackgroundWindowMask [keyWindow makeKeyWindow]; else { - var menuWindow = [CPApp mainMenu]._menuWindow; + var mainMenu = [CPApp mainMenu], + menuWindow = mainMenu ? mainMenu._menuWindow : nil; for (var i = 0; i < windowCount; i++) { var currentWindow = allWindows[i]; @@ -1961,7 +1962,8 @@ CPTexturedBackgroundWindowMask [mainWindow makeMainWindow]; else { - var menuWindow = [CPApp mainMenu]._menuWindow; + var mainMenu = [CPApp mainMenu], + menuWindow = mainMenu ? mainMenu._menuWindow : nil; for (var i = 0; i < windowCount; i++) { var currentWindow = allWindows[i]; From b1825334ddd9e25e0e54a0d22f7cbba5f4d31a15 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sat, 1 May 2010 20:40:38 -0700 Subject: [PATCH 5/9] If the vertical status changes, or the pane splitter status changes, we need to update the image value. --- AppKit/CPSplitView.j | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index d7c2bb72e..70f1a9282 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -217,10 +217,9 @@ var CPSplitViewHorizontalImage = nil, _DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat"; CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]); - - [self _setupDOMDivider]; } + [self _setupDOMDivider]; CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect)); CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); #endif From cb7879eecf5bcd9a0952b6707c24110b1236405c Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 2 May 2010 12:58:36 -0700 Subject: [PATCH 6/9] Make CFHTTPRequests re-fireable. --- Objective-J/CFHTTPRequest.js | 44 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/Objective-J/CFHTTPRequest.js b/Objective-J/CFHTTPRequest.js index f44b334db..de32c1897 100644 --- a/Objective-J/CFHTTPRequest.js +++ b/Objective-J/CFHTTPRequest.js @@ -92,16 +92,20 @@ if (!NativeRequest) GLOBAL(CFHTTPRequest) = function() { + this._requestHeaders = {}; + this._mimeType = null; + this._eventDispatcher = new EventDispatcher(this); this._nativeRequest = new NativeRequest(); var self = this; - - this._nativeRequest.onreadystatechange = function() + this._stateChangeHandler = function() { determineAndDispatchHTTPRequestEvents(self); } + this._nativeRequest.onreadystatechange = this._stateChangeHandler; + if (CFHTTPRequest.AuthenticationDelegate !== nil) this._eventDispatcher.addEventListener("HTTP403", function(){CFHTTPRequest.AuthenticationDelegate(self)}); } @@ -183,7 +187,7 @@ CFHTTPRequest.prototype.responseText = function() CFHTTPRequest.prototype.setRequestHeader = function(/*String*/ aHeader, /*Object*/ aValue) { - return this._nativeRequest.setRequestHeader(aHeader, aValue); + this._requestHeaders[aHeader] = aValue; } CFHTTPRequest.prototype.getResponseHeader = function(/*String*/ aHeader) @@ -198,17 +202,35 @@ CFHTTPRequest.prototype.getAllResponseHeaders = function() CFHTTPRequest.prototype.overrideMimeType = function(/*String*/ aMimeType) { - if ("overrideMimeType" in this._nativeRequest) - return this._nativeRequest.overrideMimeType(aMimeType); + this._mimeType = aMimeType; } CFHTTPRequest.prototype.open = function(/*String*/ aMethod, /*String*/ aURL, /*Boolean*/ isAsynchronous, /*String*/ aUser, /*String*/ aPassword) { + this._URL = aURL; + this._async = isAsynchronous; + this._method = aMethod; + this._user = aUser; + this._password = aPassword; return this._nativeRequest.open(aMethod, aURL, isAsynchronous, aUser, aPassword); } CFHTTPRequest.prototype.send = function(/*Object*/ aBody) { + delete this._nativeRequest.onreadystatechange; + + for (var i in this._requestHeaders) + { + if (this._requestHeaders.hasOwnProperty(i)) + this._nativeRequest.setRequestHeader(i, this._requestHeaders[i]); + } + + if (this._mimeType && "overrideMimeType" in this._nativeRequest) + this._nativeRequest.overrideMimeType(this._mimeType); + + this._nativeRequest.open(this._method, this._URL, this._async, this._user, this._password); + this._nativeRequest.onreadystatechange = this._stateChangeHandler; + try { return this._nativeRequest.send(aBody); @@ -242,20 +264,20 @@ function determineAndDispatchHTTPRequestEvents(/*CFHTTPRequest*/ aRequest) eventDispatcher.dispatchEvent({ type:"readystatechange", request:aRequest}); var nativeRequest = aRequest._nativeRequest, - readyState = ["uninitialized", "loading", "loaded", "interactive", "complete"][aRequest.readyState()]; + readyStates = ["uninitialized", "loading", "loaded", "interactive", "complete"]; - eventDispatcher.dispatchEvent({ type:readyState, request:aRequest}); - - if (readyState === "complete") + if (readyStates[aRequest.readyState()] === "complete") { var status = "HTTP" + aRequest.status(); - eventDispatcher.dispatchEvent({ type:status, request:aRequest }); var result = aRequest.success() ? "success" : "failure"; - eventDispatcher.dispatchEvent({ type:result, request:aRequest }); + + eventDispatcher.dispatchEvent({ type:readyStates[aRequest.readyState()], request:aRequest}); } + else + eventDispatcher.dispatchEvent({ type:readyStates[aRequest.readyState()], request:aRequest}); } function FileRequest(/*CFURL*/ aURL, onsuccess, onfailure) From af566ec08aa9a061e7f687c47c0f4b42c6c87dec Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Mon, 3 May 2010 00:25:35 -0700 Subject: [PATCH 7/9] Fix LoadTimeTest, location.host includes the port. --- Tests/Manual/LoadTimeTest/AppController.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Manual/LoadTimeTest/AppController.j b/Tests/Manual/LoadTimeTest/AppController.j index bd1f94618..1638643a2 100644 --- a/Tests/Manual/LoadTimeTest/AppController.j +++ b/Tests/Manual/LoadTimeTest/AppController.j @@ -28,7 +28,7 @@ if (data.length < 10) { // reload with data in the query string - window.location.href = [window.location.protocol, "//", window.location.host, window.location.port, window.location.pathname, "?", encodeURIComponent(JSON.stringify(data))].join(""); + window.location.href = [window.location.protocol, "//", window.location.host, window.location.pathname, "?", encodeURIComponent(JSON.stringify(data))].join(""); } else { From 50c519ec69c0ebf914acfd3197b4557aff8fcb10 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 3 May 2010 17:34:12 -0400 Subject: [PATCH 8/9] Fixed issue with CPWebView where document.body didn't exist when reloaded quickly. --- AppKit/CPWebView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPWebView.j b/AppKit/CPWebView.j index 38ddfb5fa..cd4876675 100644 --- a/AppKit/CPWebView.j +++ b/AppKit/CPWebView.j @@ -187,7 +187,7 @@ CPWebViewScrollNative = 2; var win = null; try { win = [self DOMWindow]; } catch (e) {} - if (win && win.document) + if (win && win.document && win.document.body) { var width = win.document.body.scrollWidth, height = win.document.body.scrollHeight; From 032fe7cc0cc0d5a1ef014a28f59cc76b025cb96b Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Tue, 4 May 2010 03:32:16 -0700 Subject: [PATCH 9/9] Fix for timers not working if they are created outside of a run loop. Reviewed by me. --- Foundation/CPRunLoop.j | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Foundation/CPRunLoop.j b/Foundation/CPRunLoop.j index 0884e4915..a68eead71 100644 --- a/Foundation/CPRunLoop.j +++ b/Foundation/CPRunLoop.j @@ -157,6 +157,7 @@ var CPRunLoopLastNativeRunLoop = 0; CPDate _effectiveDate; CPArray _orderedPerforms; + int _runLoopInsuranceTimer; } /* @@ -267,6 +268,12 @@ var CPRunLoopLastNativeRunLoop = 0; aTimer._lastNativeRunLoopsForModes = {}; aTimer._lastNativeRunLoopsForModes[aMode] = CPRunLoopLastNativeRunLoop; + + if (!_runLoopInsuranceTimer) + _runLoopInsuranceTimer = window.setNativeTimeout(function() + { + [self limitDateForMode:CPDefaultRunLoopMode]; + }, 0); } /*! @@ -277,9 +284,15 @@ var CPRunLoopLastNativeRunLoop = 0; //simple locking to try to prevent concurrent iterating over timers if (_runLoopLock) return; - + _runLoopLock = YES; - + + if (_runLoopInsuranceTimer) + { + window.clearNativeTimeout(_runLoopInsuranceTimer); + _runLoopInsuranceTimer = nil; + } + var now = _effectiveDate ? [_effectiveDate laterDate:[CPDate date]] : [CPDate date], nextFireDate = nil, nextTimerFireDate = _nextTimerFireDatesForModes[aMode];