Merge pull request #1204 from ianpartridge/nsnumber-se-0170

diff --git a/CoreFoundation/Base.subproj/CFPlatform.c b/CoreFoundation/Base.subproj/CFPlatform.c
index 6dd5564..896193f 100644
--- a/CoreFoundation/Base.subproj/CFPlatform.c
+++ b/CoreFoundation/Base.subproj/CFPlatform.c
@@ -1301,7 +1301,7 @@
     return (CFTypeRef)pthread_getspecific(key);
 }
 
-void _CThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) {
+void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) {
     if (value != NULL) {
         swift_retain((void *)value);
         pthread_setspecific(key, value);
diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index ea62f88..a3063c2 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -301,7 +301,7 @@
 
 typedef pthread_key_t _CFThreadSpecificKey;
 CF_EXPORT CFTypeRef _Nullable _CFThreadSpecificGet(_CFThreadSpecificKey key);
-CF_EXPORT void _CThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value);
+CF_EXPORT void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value);
 CF_EXPORT _CFThreadSpecificKey _CFThreadSpecificKeyCreate(void);
 
 typedef pthread_attr_t _CFThreadAttributes;
diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift
index f74932d..c624e7a 100644
--- a/Foundation/JSONSerialization.swift
+++ b/Foundation/JSONSerialization.swift
@@ -512,7 +512,7 @@
             } else {
                 throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
             }
-            pretty ? writer(": ") : writer(":")
+            pretty ? writer(" : ") : writer(":")
             try serializeJSON(value)
         }
 
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index 710d046..7dc8cc8 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -825,6 +825,12 @@
         CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
         return .init(truncatingIfNeeded: value.low)
     }
+
+    private var int128Value: CFSInt128Struct {
+        var value = CFSInt128Struct(high: 0, low: 0)
+        CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
+        return value
+    }
     
     open var floatValue: Float {
         var value: Float = 0
@@ -881,22 +887,26 @@
     }
 
     open func compare(_ otherNumber: NSNumber) -> ComparisonResult {
-        switch (objCType.pointee, otherNumber.objCType.pointee) {
-        case (0x66, _), (_, 0x66), (0x66, 0x66): fallthrough // 'f' float
-        case (0x64, _), (_, 0x64), (0x64, 0x64):             // 'd' double
+        switch (_cfNumberType(), otherNumber._cfNumberType()) {
+        case (kCFNumberFloatType, _), (_, kCFNumberFloatType): fallthrough
+        case (kCFNumberDoubleType, _), (_, kCFNumberDoubleType):
             let (lhs, rhs) = (doubleValue, otherNumber.doubleValue)
+            // Apply special handling for NaN as <, >, == always return false
+            // when comparing with NaN
+            if lhs.isNaN && rhs.isNaN { return .orderedSame }
+            if lhs.isNaN { return .orderedAscending }
+            if rhs.isNaN { return .orderedDescending }
+
             if lhs < rhs { return .orderedAscending }
             if lhs > rhs { return .orderedDescending }
             return .orderedSame
-        case (0x51, _), (_, 0x51), (0x51, 0x51):             // 'q' unsigned long long
-            let (lhs, rhs) = (uint64Value, otherNumber.uint64Value)
-            if lhs < rhs { return .orderedAscending }
-            if lhs > rhs { return .orderedDescending }
-            return .orderedSame
-        case (_, _):
-            let (lhs, rhs) = (int64Value, otherNumber.int64Value)
-            if lhs < rhs { return .orderedAscending }
-            if lhs > rhs { return .orderedDescending }
+
+        default: // For signed and unsigned integers expand upto S128Int
+            let (lhs, rhs) = (int128Value, otherNumber.int128Value)
+            if lhs.high < rhs.high { return .orderedAscending }
+            if lhs.high > rhs.high { return .orderedDescending }
+            if lhs.low < rhs.low { return .orderedAscending }
+            if lhs.low > rhs.low { return .orderedDescending }
             return .orderedSame
         }
     }
diff --git a/Foundation/Thread.swift b/Foundation/Thread.swift
index 340ec7f..402294d 100644
--- a/Foundation/Thread.swift
+++ b/Foundation/Thread.swift
@@ -23,13 +23,13 @@
             return specific as! T
         } else {
             let value = generator()
-            _CThreadSpecificSet(key, value)
+            _CFThreadSpecificSet(key, value)
             return value
         }
     }
 
     internal func set(_ value: T) {
-        _CThreadSpecificSet(key, value)
+        _CFThreadSpecificSet(key, value)
     }
 }
 
diff --git a/Foundation/URLSession/URLSession.swift b/Foundation/URLSession/URLSession.swift
index 3a07673..7690cc4 100644
--- a/Foundation/URLSession/URLSession.swift
+++ b/Foundation/URLSession/URLSession.swift
@@ -406,9 +406,11 @@
 
 fileprivate extension URLSession {
     func createNextTaskIdentifier() -> Int {
-        let i = nextTaskIdentifier
-        nextTaskIdentifier += 1
-        return i
+        return workQueue.sync {
+            let i = nextTaskIdentifier
+            nextTaskIdentifier += 1
+            return i
+        }
     }
 }
 
diff --git a/TestFoundation/TestJSONSerialization.swift b/TestFoundation/TestJSONSerialization.swift
index a07eba4..dabcf7f 100644
--- a/TestFoundation/TestJSONSerialization.swift
+++ b/TestFoundation/TestJSONSerialization.swift
@@ -989,6 +989,7 @@
             ("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
             ("test_serializeDecimalNumberJSONObject", test_serializeDecimalNumberJSONObject),
             ("test_serializeSortedKeys", test_serializeSortedKeys),
+            ("test_serializePrettyPrinted", test_serializePrettyPrinted),
         ]
     }
 
@@ -1479,6 +1480,11 @@
         XCTAssertEqual(try trySerialize(dict, options: .sortedKeys), "{\"a\":{\"a\":1,\"b\":1,\"c\":1},\"b\":{\"a\":1,\"b\":1,\"c\":1},\"c\":{\"a\":1,\"b\":1,\"c\":1}}")
     }
 
+    func test_serializePrettyPrinted() {
+        let dictionary = ["key": 4]
+        XCTAssertEqual(try trySerialize(dictionary, options: .prettyPrinted), "{\n  \"key\" : 4\n}")
+    }
+
     fileprivate func createTestFile(_ path: String,_contents: Data) -> String? {
         let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
         do {
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index 0e3ac08..b34d45c 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -1133,5 +1133,29 @@
         XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: Float(0)))
         XCTAssertTrue(NSNumber(value: UInt16.max) == NSNumber(value: Double(65535)))
         XCTAssertTrue(NSNumber(value: 1.1) != NSNumber(value: Int64(1)))
+        let num = NSNumber(value: Int8.min)
+        XCTAssertFalse(num == NSNumber(value: num.uint64Value))
+
+        let num1 = NSNumber(value: Float.nan)
+        XCTAssertEqual(num1.compare(num1), ComparisonResult.orderedSame)
+
+        let num2 = NSNumber(value: num1.uint8Value) // 0
+        XCTAssertFalse(num1 == num2)
+        XCTAssertFalse(num2 == num1)
+        XCTAssertEqual(num1.compare(num2), ComparisonResult.orderedAscending)
+        XCTAssertEqual(num2.compare(num1), ComparisonResult.orderedDescending)
+
+        let num3 = NSNumber(value: Double.nan)
+        XCTAssertEqual(num3.compare(num3), ComparisonResult.orderedSame)
+
+        let num4 = NSNumber(value: num3.intValue) // 0
+        XCTAssertFalse(num3 == num2)
+        XCTAssertFalse(num4 == num3)
+        XCTAssertEqual(num3.compare(num4), ComparisonResult.orderedAscending)
+        XCTAssertEqual(num4.compare(num3), ComparisonResult.orderedDescending)
+
+        XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
+        XCTAssertEqual(NSNumber(value: Double.greatestFiniteMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
+        XCTAssertTrue(NSNumber(value: Double(-0.0)) == NSNumber(value: Double(0.0)))
     }
 }