[iOS] Protect timer module for NAN value.
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h
index 7523cf9..0800003 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h
@@ -89,6 +89,8 @@
     WX_KEY_EXCEPTION_DOM = -9300,
     WX_KEY_EXCEPTION_WXBRIDGE=-9400,
     WX_KEY_EXCEPTION_JS_THREAD_BLOCK=-9401,
+    WX_KEY_EXCEPTION_JS_TIMER_TIMEOUT_NAN=-9402,
+    WX_KEY_EXCEPTION_JS_TIMER_REPEAT_HIGH_FREQUENCY=-9403,
     
     // The following error codes have a remapped value defined in WXSDKUniversalErrCode
     WX_KEY_EXCEPTION_DEGRADE = -9500,
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
index 755cdd1..132e08d 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
@@ -89,6 +89,8 @@
                 @(WX_KEY_EXCEPTION_DOM):@{ERROR_TYPE:@(WX_NATIVE_ERROR),ERROR_GROUP:@(WX_NATIVE)},
                 @(WX_KEY_EXCEPTION_WXBRIDGE):@{ERROR_TYPE:@(WX_JS_ERROR),ERROR_GROUP:@(WX_JS)},
                 @(WX_KEY_EXCEPTION_JS_THREAD_BLOCK):@{ERROR_TYPE:@(WX_JS_ERROR),ERROR_GROUP:@(WX_JS)},
+                @(WX_KEY_EXCEPTION_JS_TIMER_TIMEOUT_NAN):@{ERROR_TYPE:@(WX_JS_ERROR),ERROR_GROUP:@(WX_JS)},
+                @(WX_KEY_EXCEPTION_JS_TIMER_REPEAT_HIGH_FREQUENCY):@{ERROR_TYPE:@(WX_JS_ERROR),ERROR_GROUP:@(WX_JS)},
                 
                 @(WX_KEY_EXCEPTION_DEGRADE):@{ERROR_TYPE:@(WX_DEGRADE_ERROR),ERROR_GROUP:@(WX_NATIVE),ERROR_ALIAS:@(WX_UNI_KEY_EXCEPTION_DEGRADE)},
                 @(WX_KEY_EXCEPTION_DEGRADE_CHECK_CONTENT_LENGTH_FAILED):@{ERROR_TYPE:@(WX_DEGRADE_ERROR),ERROR_GROUP:@(WX_NET),ERROR_ALIAS:@(WX_UNI_KEY_EXCEPTION_DEGRADE_CHECK_CONTENT_LENGTH_FAILED)},
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m b/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m
index 2a50189..0494298 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m
@@ -77,6 +77,8 @@
 
 @implementation WXTimerModule
 {
+    BOOL _timeoutNANReported;
+    BOOL _timeoutRepeatReported;
     NSMutableDictionary *_timers;
 }
 
@@ -164,9 +166,29 @@
     WXAssert(!isnan(milliseconds), @"Timer interval is NAN.");
     if (isnan(milliseconds)) { //!OCLint
         WXLogError(@"Create timer with NAN interval.");
+        
+        if (!_timeoutNANReported) {
+            [WXExceptionUtils commitCriticalExceptionRT:self.weexInstance.instanceId errCode:[NSString stringWithFormat:@"%d", WX_KEY_EXCEPTION_JS_TIMER_TIMEOUT_NAN] function:@"" exception:@"Time out is NAN." extParams:nil];
+            _timeoutNANReported = YES;
+        }
+        
+        if (shouldRepeat) {
+            /* NAN for repeatable timer, we ignore.
+             For iOS, scheduledTimerWithTimeInterval with NAN and repeate as YES would crash. */
+        }
+        else {
+            [[WXSDKManager bridgeMgr] callBack:self.weexInstance.instanceId funcId:callbackID params:nil keepAlive:NO];
+        }
         return;
     }
     
+    if (milliseconds < 100 && shouldRepeat) {
+        if (!_timeoutRepeatReported) {
+            [WXExceptionUtils commitCriticalExceptionRT:self.weexInstance.instanceId errCode:[NSString stringWithFormat:@"%d", WX_KEY_EXCEPTION_JS_TIMER_REPEAT_HIGH_FREQUENCY] function:@"" exception:[NSString stringWithFormat:@"Repeated timer's timeout value too short. %fms", milliseconds] extParams:nil];
+            _timeoutRepeatReported = YES;
+        }
+    }
+    
     NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds/1000.0f target:target selector:selector userInfo:nil repeats:shouldRepeat];
     [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];