Merge pull request #1086 from skyline75489/fix/NSUserDefaults-dictionaryRepresentation

diff --git a/CoreFoundation/Base.subproj/CFRuntime.c b/CoreFoundation/Base.subproj/CFRuntime.c
index d7550a4..ead676d 100644
--- a/CoreFoundation/Base.subproj/CFRuntime.c
+++ b/CoreFoundation/Base.subproj/CFRuntime.c
@@ -1699,15 +1699,6 @@
     }
 }
 
-// For CF functions with 'Get' semantics, the compiler currently assumes that the result is autoreleased and must be retained. It does so on all platforms by emitting a call to objc_retainAutoreleasedReturnValue. On Darwin, this is implemented by the ObjC runtime. On Linux, there is no runtime, and therefore we have to stub it out here ourselves. The compiler will eventually call swift_release to balance the retain below. This is a workaround until the compiler no longer emits this callout on Linux.
-void * objc_retainAutoreleasedReturnValue(void *obj) {
-    if (obj) {
-        swift_retain(obj);
-        return obj;
-    }
-    else return NULL;
-}
-        
 CFHashCode __CFHashDouble(double d) {
     return _CFHashDouble(d);
 }
diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index d6d28ff..c1e3610 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -254,6 +254,8 @@
 
 CF_EXPORT void _CFRuntimeBridgeTypeToClass(CFTypeID type, const void *isa);
 
+CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number);
+
 typedef	unsigned char __cf_uuid[16];
 typedef	char __cf_uuid_string[37];
 typedef __cf_uuid _cf_uuid_t;
diff --git a/CoreFoundation/NumberDate.subproj/CFTimeZone.c b/CoreFoundation/NumberDate.subproj/CFTimeZone.c
index 434203a..427a3b1 100644
--- a/CoreFoundation/NumberDate.subproj/CFTimeZone.c
+++ b/CoreFoundation/NumberDate.subproj/CFTimeZone.c
@@ -33,9 +33,12 @@
 #endif
 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <tzfile.h>
+#define MACOS_TZDIR1 "/usr/share/zoneinfo/"          // 10.12 and earlier
+#define MACOS_TZDIR2 "/var/db/timezone/zoneinfo/"    // 10.13 onwards
+
 #elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 #ifndef TZDIR
-#define TZDIR	"/usr/share/zoneinfo" /* Time zone object file directory */
+#define TZDIR	"/usr/share/zoneinfo/" /* Time zone object file directory */
 #endif /* !defined TZDIR */
 
 #ifndef TZDEFAULT
@@ -56,16 +59,9 @@
 
 #include <time.h>
 
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-#define TZZONELINK	TZDEFAULT
-#define TZZONEINFO	TZDIR "/"
-#elif DEPLOYMENT_TARGET_WINDOWS
 static CFStringRef __tzZoneInfo = NULL;
 static char *__tzDir = NULL;
 static void __InitTZStrings(void);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
 
 CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification, "kCFTimeZoneSystemTimeZoneDidChangeNotification")
 
@@ -147,13 +143,9 @@
 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 static CFMutableArrayRef __CFCopyRecursiveDirectoryList() {
     CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
-#if DEPLOYMENT_TARGET_WINDOWS
     if (!__tzDir) __InitTZStrings();
     if (!__tzDir) return result;
     int fd = open(__tzDir, O_RDONLY);
-#else
-    int fd = open(TZDIR "/zone.tab", O_RDONLY);
-#endif
 
     for (; 0 <= fd;) {
         uint8_t buffer[4096];
@@ -686,7 +678,7 @@
 }
 
 extern CFStringRef _CFGetWindowsAppleSystemLibraryDirectory(void);
-void __InitTZStrings(void) {
+static void __InitTZStrings(void) {
     static CFLock_t __CFTZDirLock = CFLockInit;
     __CFLock(&__CFTZDirLock);
     if (!__tzZoneInfo) {
@@ -704,6 +696,50 @@
     }
     __CFUnlock(&__CFTZDirLock);
 }
+
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+static void __InitTZStrings(void) {
+    static dispatch_once_t initOnce = 0;
+
+    dispatch_once(&initOnce, ^{
+        unsigned int major = 0, minor = 0, patch = 0;
+
+        CFDictionaryRef dict = _CFCopySystemVersionDictionary();
+        if (dict) {
+            CFStringRef version = CFDictionaryGetValue(dict, _kCFSystemVersionProductVersionKey);
+            if (version) {
+                const char *cStr = CFStringGetCStringPtr(version, kCFStringEncodingASCII);
+                if (cStr) {
+                    if (sscanf(cStr, "%u.%u.%u", &major, &minor, &patch) != 3) {
+                        major = 0;
+                        minor = 0;
+                        patch = 0;
+                    }
+                }
+            }
+            CFRelease(dict);
+        }
+
+        // Timezone files moved in High Sierra(10.13)
+        if (major == 10 && minor < 13) {
+            // older versions
+            __tzZoneInfo = CFSTR(MACOS_TZDIR1);
+            __tzDir = MACOS_TZDIR1 "zone.tab";
+        } else {
+            __tzZoneInfo = CFSTR(MACOS_TZDIR2);
+            __tzDir = MACOS_TZDIR2 "zone.tab";
+        }
+    });
+}
+
+#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+static void __InitTZStrings(void) {
+    __tzZoneInfo = CFSTR(TZDIR);
+    __tzDir = TZDIR "zone.tab";
+}
+
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
@@ -748,11 +784,16 @@
         CFRelease(name);
         if (result) return result;
     }
-    ret = readlink(TZZONELINK, linkbuf, sizeof(linkbuf));
-    if (0 < ret) {
+
+    if (!__tzZoneInfo) __InitTZStrings();
+    ret = readlink(TZDEFAULT, linkbuf, sizeof(linkbuf));
+    if (__tzZoneInfo && (0 < ret)) {
         linkbuf[ret] = '\0';
-        if (strncmp(linkbuf, TZZONEINFO, sizeof(TZZONEINFO) - 1) == 0) {
-            name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + sizeof(TZZONEINFO) - 1, strlen(linkbuf) - sizeof(TZZONEINFO) + 1, kCFStringEncodingUTF8, false);
+        const char *tzZoneInfo = CFStringGetCStringPtr(__tzZoneInfo, kCFStringEncodingASCII);
+        size_t zoneInfoDirLen = CFStringGetLength(__tzZoneInfo);
+        if (strncmp(linkbuf, tzZoneInfo, zoneInfoDirLen) == 0) {
+            name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + zoneInfoDirLen,
+                                           strlen(linkbuf) - zoneInfoDirLen + 2, kCFStringEncodingUTF8, false);
         } else {
             name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
         }
@@ -1133,12 +1174,12 @@
             CFIndex length;
             Boolean result = false;
             
-#if DEPLOYMENT_TARGET_WINDOWS
             if (!__tzZoneInfo) __InitTZStrings();
             if (!__tzZoneInfo) return NULL;
+#if DEPLOYMENT_TARGET_WINDOWS
             baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
 #else
-            baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
+            baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLPOSIXPathStyle, true);
 #endif
             if (tryAbbrev) {
                 CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
@@ -1159,15 +1200,9 @@
                 CFStringRef mapping = CFDictionaryGetValue(dict, name);
                 if (mapping) {
                     name = mapping;
-#if DEPLOYMENT_TARGET_WINDOWS
                 } else if (CFStringHasPrefix(name, __tzZoneInfo)) {
                     CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
                     CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
-#else
-                } else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
-                    CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
-                    CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
-#endif
                     mapping = CFDictionaryGetValue(dict, unprefixed);
                     if (mapping) {
                         name = mapping;
@@ -1340,12 +1375,12 @@
     void *bytes;
     CFIndex length;
 
-#if DEPLOYMENT_TARGET_WINDOWS
     if (!__tzZoneInfo) __InitTZStrings();
     if (!__tzZoneInfo) return NULL;
+#if DEPLOYMENT_TARGET_WINDOWS
     baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
 #else
-    baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
+    baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLPOSIXPathStyle, true);
 #endif
     if (tryAbbrev) {
 	CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
@@ -1366,15 +1401,9 @@
 	CFStringRef mapping = CFDictionaryGetValue(dict, name);
 	if (mapping) {
 	    name = mapping;
-#if DEPLOYMENT_TARGET_WINDOWS
 	} else if (CFStringHasPrefix(name, __tzZoneInfo)) {
 	    CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
 	    CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
-#else
-	} else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
-	    CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
-	    CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
-#endif
 	    mapping = CFDictionaryGetValue(dict, unprefixed);
 	    if (mapping) {
 		name = mapping;
@@ -1549,6 +1578,4 @@
     return dict;
 }
 
-#undef TZZONEINFO
-#undef TZZONELINK
 
diff --git a/CoreFoundation/Parsing.subproj/CFXMLInterface.c b/CoreFoundation/Parsing.subproj/CFXMLInterface.c
index 97f9340..0c1dbae 100644
--- a/CoreFoundation/Parsing.subproj/CFXMLInterface.c
+++ b/CoreFoundation/Parsing.subproj/CFXMLInterface.c
@@ -20,6 +20,7 @@
 #include <libxml/xmlmemory.h>
 #include <libxml/xmlsave.h>
 #include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
 #include <libxml/dict.h>
 #include "CFInternal.h"
 
@@ -57,6 +58,7 @@
 CFIndex _kCFXMLTypeAttribute = XML_ATTRIBUTE_NODE;
 CFIndex _kCFXMLTypeDTD = XML_DTD_NODE;
 CFIndex _kCFXMLDocTypeHTML = XML_DOC_HTML;
+CFIndex _kCFXMLTypeNamespace = 22; // libxml2 does not define namespaces as nodes, so we have to fake it
 
 CFIndex _kCFXMLDTDNodeTypeEntity = XML_ENTITY_DECL;
 CFIndex _kCFXMLDTDNodeTypeAttribute = XML_ATTRIBUTE_DECL;
@@ -360,11 +362,7 @@
     return xmlNewProp(node, name, value);
 }
 
-_CFXMLNamespacePtr _CFXMLNewNamespace(_CFXMLNodePtr node, const unsigned char* uri, const unsigned char* prefix) {
-    return xmlNewNs(node, uri, prefix);
-}
-
-CF_RETURNS_RETAINED CFStringRef _CFXMLNodeURI(_CFXMLNodePtr node) {
+CFStringRef _CFXMLNodeCopyURI(_CFXMLNodePtr node) {
     xmlNodePtr nodePtr = (xmlNodePtr)node;
     switch (nodePtr->type) {
         case XML_ATTRIBUTE_NODE:
@@ -447,15 +445,51 @@
     return ((xmlNodePtr)node)->type;
 }
 
-const char* _CFXMLNodeGetName(_CFXMLNodePtr node) {
-    return (const char*)(((xmlNodePtr)node)->name);
+static inline xmlChar* _getQName(xmlNodePtr node) {
+    const xmlChar* prefix = NULL;
+    const xmlChar* ncname = node->name;
+    
+    switch (node->type) {
+        case XML_NOTATION_NODE:
+        case XML_DTD_NODE:
+        case XML_ELEMENT_DECL:
+        case XML_ATTRIBUTE_DECL:
+        case XML_ENTITY_DECL:
+        case XML_NAMESPACE_DECL:
+        case XML_XINCLUDE_START:
+        case XML_XINCLUDE_END:
+            break;
+            
+        default:
+            if (node->ns != NULL) {
+                prefix = node->ns->prefix;
+            }
+    }
+    
+    return xmlBuildQName(ncname, prefix, NULL, 0);
+}
+
+CFStringRef _Nullable _CFXMLNodeCopyName(_CFXMLNodePtr node) {
+    xmlNodePtr xmlNode = (xmlNodePtr)node;
+    
+    xmlChar* qName = _getQName(xmlNode);
+    
+    if (qName != NULL) {
+        CFStringRef result = CFStringCreateWithCString(NULL, (const char*)qName, kCFStringEncodingUTF8);
+        if (qName != xmlNode->name) {
+            xmlFree(qName);
+        }
+        return result;
+    } else {
+        return NULL;
+    }
 }
 
 void _CFXMLNodeSetName(_CFXMLNodePtr node, const char* name) {
     xmlNodeSetName(node, (const xmlChar*)name);
 }
 
-CFStringRef _CFXMLNodeGetContent(_CFXMLNodePtr node) {
+CFStringRef _CFXMLNodeCopyContent(_CFXMLNodePtr node) {
     switch (((xmlNodePtr)node)->type) {
         case XML_ELEMENT_DECL:
         {
@@ -497,7 +531,7 @@
             // xmlElementContent structures, let's leverage what we've already got.
             CFMutableStringRef xmlString = CFStringCreateMutable(NULL, 0);
             CFStringAppend(xmlString, CFSTR("<!ELEMENT "));
-            CFStringAppendCString(xmlString, _CFXMLNodeGetName(node), kCFStringEncodingUTF8);
+            CFStringAppendCString(xmlString, (const char*)element->name, kCFStringEncodingUTF8);
             CFStringAppend(xmlString, CFSTR(" "));
             CFStringAppendCString(xmlString, (const char*)content, kCFStringEncodingUTF8);
             CFStringAppend(xmlString, CFSTR(">"));
@@ -647,7 +681,7 @@
     xmlDocSetRootElement(doc, node);
 }
 
-CF_RETURNS_RETAINED CFStringRef _CFXMLDocCharacterEncoding(_CFXMLDocPtr doc) {
+CFStringRef _CFXMLDocCopyCharacterEncoding(_CFXMLDocPtr doc) {
     return CFStringCreateWithCString(NULL, (const char*)((xmlDocPtr)doc)->encoding, kCFStringEncodingUTF8);
 }
 
@@ -661,7 +695,7 @@
     docPtr->encoding = xmlStrdup(encoding);
 }
 
-CF_RETURNS_RETAINED CFStringRef _CFXMLDocVersion(_CFXMLDocPtr doc) {
+CFStringRef _CFXMLDocCopyVersion(_CFXMLDocPtr doc) {
     return CFStringCreateWithCString(NULL, (const char*)((xmlDocPtr)doc)->version, kCFStringEncodingUTF8);
 }
 
@@ -748,7 +782,7 @@
     return xmlGetParameterEntity(doc, (const xmlChar*)entity);
 }
 
-CFStringRef _CFXMLGetEntityContent(_CFXMLEntityPtr entity) {
+CFStringRef _CFXMLCopyEntityContent(_CFXMLEntityPtr entity) {
     const xmlChar* content = ((xmlEntityPtr)entity)->content;
     if (!content) {
         return NULL;
@@ -760,7 +794,7 @@
     return result;
 }
 
-CFStringRef _CFXMLStringWithOptions(_CFXMLNodePtr node, uint32_t options) {
+CFStringRef _CFXMLCopyStringWithOptions(_CFXMLNodePtr node, uint32_t options) {
     if (((xmlNodePtr)node)->type == XML_ENTITY_DECL &&
         ((xmlEntityPtr)node)->etype == XML_INTERNAL_PREDEFINED_ENTITY) {
         // predefined entities need special handling, libxml2 just tosses an error and returns a NULL string
@@ -832,17 +866,26 @@
     return result;
 }
 
-CF_RETURNS_RETAINED CFArrayRef _CFXMLNodesForXPath(_CFXMLNodePtr node, const unsigned char* xpath) {
+CFArrayRef _CFXMLNodesForXPath(_CFXMLNodePtr node, const unsigned char* xpath) {
 
     if (((xmlNodePtr)node)->doc == NULL) {
         return NULL;
     }
-
+    
+    if (((xmlNodePtr)node)->type == XML_DOCUMENT_NODE) {
+        node = ((xmlDocPtr)node)->children;
+    }
+    
     xmlXPathContextPtr context = xmlXPathNewContext(((xmlNodePtr)node)->doc);
+    xmlNsPtr ns = ((xmlNodePtr)node)->ns;
+    while (ns != NULL) {
+        xmlXPathRegisterNs(context, ns->prefix, ns->href);
+        ns = ns->next;
+    }
     xmlXPathObjectPtr evalResult = xmlXPathNodeEval(node, xpath, context);
 
     xmlNodeSetPtr nodes = evalResult->nodesetval;
-
+    
     int count = nodes->nodeNr;
 
     CFMutableArrayRef results = CFArrayCreateMutable(NULL, count, NULL);
@@ -856,8 +899,15 @@
     return results;
 }
 
-_CFXMLNodePtr _CFXMLNodeHasProp(_CFXMLNodePtr node, const unsigned char* propertyName) {
-    return xmlHasProp(node, propertyName);
+CFStringRef _Nullable _CFXMLCopyPathForNode(_CFXMLNodePtr node) {
+    xmlChar* path = xmlGetNodePath(node);
+    CFStringRef result = CFStringCreateWithCString(NULL, (const char*)path, kCFStringEncodingUTF8);
+    xmlFree(path);
+    return result;
+}
+
+_CFXMLNodePtr _CFXMLNodeHasProp(_CFXMLNodePtr node, const char* propertyName) {
+    return xmlHasProp(node, (const xmlChar*)propertyName);
 }
 
 _CFXMLDocPtr _CFXMLDocPtrFromDataWithOptions(CFDataRef data, int options) {
@@ -876,19 +926,26 @@
     if (options & _kCFXMLNodeLoadExternalEntitiesAlways) {
         xmlOptions |= XML_PARSE_DTDLOAD;
     }
-
+    
+    xmlOptions |= XML_PARSE_RECOVER;
+    xmlOptions |= XML_PARSE_NSCLEAN;
+    
     return xmlReadMemory((const char*)CFDataGetBytePtr(data), CFDataGetLength(data), NULL, NULL, xmlOptions);
 }
 
-CF_RETURNS_RETAINED CFStringRef _CFXMLNodeLocalName(_CFXMLNodePtr node) {
-    int length = 0;
-    const xmlChar* result = xmlSplitQName3(((xmlNodePtr)node)->name, &length);
+CFStringRef _CFXMLNodeCopyLocalName(_CFXMLNodePtr node) {
+    xmlChar* prefix = NULL;
+    const xmlChar* result = xmlSplitQName2(_getQName((xmlNodePtr)node), &prefix);
+    if (result == NULL) {
+        result = ((xmlNodePtr)node)->name;
+    }
+    
     return CFStringCreateWithCString(NULL, (const char*)result, kCFStringEncodingUTF8);
 }
 
-CF_RETURNS_RETAINED CFStringRef _CFXMLNodePrefix(_CFXMLNodePtr node) {
+CFStringRef _CFXMLNodeCopyPrefix(_CFXMLNodePtr node) {
     xmlChar* result = NULL;
-    xmlChar* unused = xmlSplitQName2(((xmlNodePtr)node)->name, &result);
+    xmlChar* unused = xmlSplitQName2(_getQName((xmlNodePtr)node), &result);
 
     CFStringRef resultString = CFStringCreateWithCString(NULL, (const char*)result, kCFStringEncodingUTF8);
     xmlFree(result);
@@ -983,7 +1040,7 @@
     return dtd;
 }
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDExternalID(_CFXMLDTDPtr dtd) {
+CFStringRef _Nullable _CFXMLDTDCopyExternalID(_CFXMLDTDPtr dtd) {
     const unsigned char* externalID = ((xmlDtdPtr)dtd)->ExternalID;
     if (externalID) {
         return CFStringCreateWithCString(NULL, (const char*)externalID, kCFStringEncodingUTF8);
@@ -1008,7 +1065,7 @@
     dtdPtr->ExternalID = xmlStrdup(externalID);
 }
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDSystemID(_CFXMLDTDPtr dtd) {
+CFStringRef _Nullable _CFXMLDTDCopySystemID(_CFXMLDTDPtr dtd) {
     const unsigned char* systemID = ((xmlDtdPtr)dtd)->SystemID;
     if (systemID) {
         return CFStringCreateWithCString(NULL, (const char*)systemID, kCFStringEncodingUTF8);
@@ -1095,7 +1152,7 @@
     return ((xmlAttributePtr)node)->atype;
 }
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDNodeGetSystemID(_CFXMLDTDNodePtr node) {
+CFStringRef _Nullable _CFXMLDTDNodeCopySystemID(_CFXMLDTDNodePtr node) {
     switch (((xmlNodePtr)node)->type) {
         case XML_ENTITY_DECL:
             return CFStringCreateWithCString(NULL, (const char*)((xmlEntityPtr)node)->SystemID, kCFStringEncodingUTF8);
@@ -1137,7 +1194,7 @@
     }
 }
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDNodeGetPublicID(_CFXMLDTDNodePtr node) {
+CFStringRef _Nullable _CFXMLDTDNodeCopyPublicID(_CFXMLDTDNodePtr node) {
     switch (((xmlNodePtr)node)->type) {
         case XML_ENTITY_DECL:
             return CFStringCreateWithCString(NULL, (const char*)((xmlEntityPtr)node)->ExternalID, kCFStringEncodingUTF8);
@@ -1179,6 +1236,131 @@
     }
 }
 
+// Namespaces
+_CFXMLNodePtr _Nonnull * _Nullable _CFXMLNamespaces(_CFXMLNodePtr node, CFIndex* count) {
+    *count = 0;
+    xmlNs* ns = ((xmlNode*)node)->ns;
+    while (ns != NULL) {
+        (*count)++;
+        ns = ns->next;
+    }
+    
+    _CFXMLNodePtr* result = calloc(*count, sizeof(_CFXMLNodePtr));
+    ns = ((xmlNode*)node)->ns;
+    for (int i = 0; i < *count; i++) {
+        xmlNode* temp = xmlNewNode(ns, (unsigned char *)"");
+        
+        temp->type = _kCFXMLTypeNamespace;
+        result[i] = temp;
+        ns = ns->next;
+    }
+    return result;
+}
+
+static inline void _removeAllNamespaces(xmlNodePtr node);
+static inline void _removeAllNamespaces(xmlNodePtr node) {
+    xmlNsPtr ns = node->ns;
+    if (ns != NULL) {
+        xmlFreeNsList(ns);
+        node->ns = NULL;
+    }
+}
+
+void _CFXMLSetNamespaces(_CFXMLNodePtr node, _CFXMLNodePtr* _Nullable nodes, CFIndex count) {
+    _removeAllNamespaces(node);
+    
+    if (nodes == NULL || count == 0) {
+        return;
+    }
+    
+    xmlNodePtr nsNode = (xmlNodePtr)nodes[0];
+    ((xmlNodePtr)node)->ns = xmlCopyNamespace(nsNode->ns);
+    xmlNsPtr currNs = ((xmlNodePtr)node)->ns;
+    for (CFIndex i = 1; i < count; i++) {
+        currNs->next = xmlCopyNamespace(((xmlNodePtr)nodes[i])->ns);
+        currNs = currNs->next;
+    }
+}
+
+CFStringRef _Nullable _CFXMLNamespaceCopyValue(_CFXMLNodePtr node) {
+    xmlNsPtr ns = ((xmlNode*)node)->ns;
+    
+    if (ns->href == NULL) {
+        return NULL;
+    }
+    
+    return CFStringCreateWithCString(NULL, (const char*)ns->href, kCFStringEncodingUTF8);
+}
+
+void _CFXMLNamespaceSetValue(_CFXMLNodePtr node, const char* value, int64_t length) {
+    xmlNsPtr ns = ((xmlNodePtr)node)->ns;
+    ns->href = xmlStrndup((const xmlChar*)value, length);
+}
+
+CFStringRef _Nullable _CFXMLNamespaceCopyPrefix(_CFXMLNodePtr node) {
+    xmlNsPtr ns = ((xmlNodePtr)node)->ns;
+    
+    if (ns->prefix == NULL) {
+        return NULL;
+    }
+    
+    return CFStringCreateWithCString(NULL, (const char*)ns->prefix, kCFStringEncodingUTF8);
+}
+
+void _CFXMLNamespaceSetPrefix(_CFXMLNodePtr node, const char* prefix, int64_t length) {
+    xmlNsPtr ns = ((xmlNodePtr)node)->ns;
+    
+    ns->prefix = xmlStrndup((const xmlChar*)prefix, length);
+}
+
+_CFXMLNodePtr _CFXMLNewNamespace(const char* name, const char* stringValue) {
+    xmlNsPtr ns = xmlNewNs(NULL, (const xmlChar*)stringValue, (const xmlChar*)name);
+    xmlNodePtr node = xmlNewNode(ns, (const xmlChar*)"");
+    
+    node->type = _kCFXMLTypeNamespace;
+        
+    return node;
+}
+
+void _CFXMLAddNamespace(_CFXMLNodePtr node, _CFXMLNodePtr nsNode) {
+    xmlNodePtr nodePtr = (xmlNodePtr)node;
+    xmlNsPtr ns = xmlCopyNamespace(((xmlNodePtr)nsNode)->ns);
+    ns->context = nodePtr->doc;
+    
+    xmlNsPtr currNs = nodePtr->ns;
+    if (currNs == NULL) {
+        nodePtr->ns = ns;
+        return;
+    }
+    
+    while(currNs->next != NULL) {
+        currNs = currNs->next;
+    }
+    
+    currNs->next = ns;
+}
+
+void _CFXMLRemoveNamespace(_CFXMLNodePtr node, const char* prefix) {
+    xmlNodePtr nodePtr = (xmlNodePtr)node;
+    xmlNsPtr ns = nodePtr->ns;
+    if (ns != NULL && xmlStrcmp((const xmlChar*)prefix, ns->prefix) == 0) {
+        nodePtr->ns = ns->next;
+        xmlFreeNs(ns);
+        return;
+    }
+    
+    while (ns->next != NULL) {
+        if (xmlStrcmp(ns->next->prefix, (const xmlChar*)prefix) == 0) {
+            xmlNsPtr next = ns->next;
+            ns->next = ns->next->next;
+            xmlFreeNs(next);
+            return;
+        }
+        
+        ns = ns->next;
+    }
+}
+
 void _CFXMLFreeNode(_CFXMLNodePtr node) {
     if (!node) {
         return;
@@ -1231,6 +1413,13 @@
         }
 
         default:
+            // we first need to check if this node is one of our custom
+            // namespace nodes, which don't actually exist in libxml2
+            if (((xmlNodePtr)node)->type == _kCFXMLTypeNamespace) {
+                // resetting its type to XML_ELEMENT_NODE will cause the enclosed namespace
+                // to be properly freed by libxml2
+                ((xmlNodePtr)node)->type = XML_ELEMENT_NODE;
+            }
             xmlFreeNode(node);
     }
 }
diff --git a/CoreFoundation/Parsing.subproj/CFXMLInterface.h b/CoreFoundation/Parsing.subproj/CFXMLInterface.h
index bd9f6fe..f9ac170 100644
--- a/CoreFoundation/Parsing.subproj/CFXMLInterface.h
+++ b/CoreFoundation/Parsing.subproj/CFXMLInterface.h
@@ -55,6 +55,7 @@
 extern CFIndex _kCFXMLTypeAttribute;
 extern CFIndex _kCFXMLTypeDTD;
 extern CFIndex _kCFXMLDocTypeHTML;
+extern CFIndex _kCFXMLTypeNamespace;
 
 extern CFIndex _kCFXMLDTDNodeTypeEntity;
 extern CFIndex _kCFXMLDTDNodeTypeAttribute;
@@ -144,18 +145,17 @@
 _CFXMLNodePtr _CFXMLNewTextNode(const unsigned char* value);
 _CFXMLNodePtr _CFXMLNewComment(const unsigned char* value);
 _CFXMLNodePtr _CFXMLNewProperty(_CFXMLNodePtr _Nullable node, const unsigned char* name, const unsigned char* value);
-_CFXMLNamespacePtr _CFXMLNewNamespace(_CFXMLNodePtr _Nullable node, const unsigned char* uri, const unsigned char* prefix);
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLNodeURI(_CFXMLNodePtr node);
+CFStringRef _Nullable _CFXMLNodeCopyURI(_CFXMLNodePtr node);
 void _CFXMLNodeSetURI(_CFXMLNodePtr node, const unsigned char* _Nullable URI);
 
 void _CFXMLNodeSetPrivateData(_CFXMLNodePtr node, void* data);
 void* _Nullable  _CFXMLNodeGetPrivateData(_CFXMLNodePtr node);
 _CFXMLNodePtr _Nullable _CFXMLNodeProperties(_CFXMLNodePtr node);
 CFIndex _CFXMLNodeGetType(_CFXMLNodePtr node);
-const char* _Nullable _CFXMLNodeGetName(_CFXMLNodePtr node);
+CFStringRef _Nullable _CFXMLNodeCopyName(_CFXMLNodePtr node);
 void _CFXMLNodeSetName(_CFXMLNodePtr node, const char* name);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLNodeGetContent(_CFXMLNodePtr node);
+CFStringRef _Nullable _CFXMLNodeCopyContent(_CFXMLNodePtr node);
 void _CFXMLNodeSetContent(_CFXMLNodePtr node,  const unsigned char* _Nullable content);
 void _CFXMLUnlinkNode(_CFXMLNodePtr node);
 
@@ -176,9 +176,9 @@
 void _CFXMLDocSetStandalone(_CFXMLDocPtr doc, bool standalone);
 _CFXMLNodePtr _Nullable _CFXMLDocRootElement(_CFXMLDocPtr doc);
 void _CFXMLDocSetRootElement(_CFXMLDocPtr doc, _CFXMLNodePtr node);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDocCharacterEncoding(_CFXMLDocPtr doc);
+CFStringRef _Nullable _CFXMLDocCopyCharacterEncoding(_CFXMLDocPtr doc);
 void _CFXMLDocSetCharacterEncoding(_CFXMLDocPtr doc,  const unsigned char* _Nullable  encoding);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDocVersion(_CFXMLDocPtr doc);
+CFStringRef _Nullable _CFXMLDocCopyVersion(_CFXMLDocPtr doc);
 void _CFXMLDocSetVersion(_CFXMLDocPtr doc, const unsigned char* _Nullable version);
 int _CFXMLDocProperties(_CFXMLDocPtr doc);
 void _CFXMLDocSetProperties(_CFXMLDocPtr doc, int newProperties);
@@ -190,18 +190,19 @@
 _CFXMLEntityPtr _Nullable _CFXMLGetDTDEntity(_CFXMLDocPtr doc, const char* entity);
 _CFXMLEntityPtr _Nullable _CFXMLGetParameterEntity(_CFXMLDocPtr doc, const char* entity);
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLGetEntityContent(_CFXMLEntityPtr entity);
+CFStringRef _Nullable _CFXMLCopyEntityContent(_CFXMLEntityPtr entity);
 
-CF_RETURNS_RETAINED CFStringRef _CFXMLStringWithOptions(_CFXMLNodePtr node, uint32_t options);
+CFStringRef _CFXMLCopyStringWithOptions(_CFXMLNodePtr node, uint32_t options);
 
 CF_RETURNS_RETAINED CFArrayRef _Nullable _CFXMLNodesForXPath(_CFXMLNodePtr node, const unsigned char* xpath);
+CFStringRef _Nullable _CFXMLCopyPathForNode(_CFXMLNodePtr node);
 
-_CFXMLNodePtr _Nullable _CFXMLNodeHasProp(_CFXMLNodePtr node, const unsigned char* propertyName);
+_CFXMLNodePtr _Nullable _CFXMLNodeHasProp(_CFXMLNodePtr node, const char* propertyName);
 
 _CFXMLDocPtr _CFXMLDocPtrFromDataWithOptions(CFDataRef data, int options);
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLNodeLocalName(_CFXMLNodePtr node);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLNodePrefix(_CFXMLNodePtr node);
+CFStringRef _Nullable _CFXMLNodeCopyLocalName(_CFXMLNodePtr node);
+CFStringRef _Nullable _CFXMLNodeCopyPrefix(_CFXMLNodePtr node);
 
 bool _CFXMLDocValidate(_CFXMLDocPtr doc, CFErrorRef _Nullable * error);
 
@@ -209,9 +210,9 @@
 _CFXMLDTDNodePtr _Nullable _CFXMLParseDTDNode(const unsigned char* xmlString);
 _CFXMLDTDPtr _Nullable _CFXMLParseDTD(const unsigned char* URL);
 _CFXMLDTDPtr _Nullable _CFXMLParseDTDFromData(CFDataRef data, CFErrorRef _Nullable * error);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDExternalID(_CFXMLDTDPtr dtd);
+CFStringRef _Nullable _CFXMLDTDCopyExternalID(_CFXMLDTDPtr dtd);
 void _CFXMLDTDSetExternalID(_CFXMLDTDPtr dtd, const unsigned char* _Nullable externalID);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDSystemID(_CFXMLDTDPtr dtd);
+CFStringRef _Nullable _CFXMLDTDCopySystemID(_CFXMLDTDPtr dtd);
 void _CFXMLDTDSetSystemID(_CFXMLDTDPtr dtd, const unsigned char* _Nullable systemID);
 
 _CFXMLDTDNodePtr _Nullable _CFXMLDTDGetElementDesc(_CFXMLDTDPtr dtd, const unsigned char* name);
@@ -227,11 +228,22 @@
 CFIndex _CFXMLDTDEntityNodeGetType(_CFXMLDTDNodePtr node);
 CFIndex _CFXMLDTDAttributeNodeGetType(_CFXMLDTDNodePtr node);
 
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDNodeGetSystemID(_CFXMLDTDNodePtr node);
+CFStringRef _Nullable _CFXMLDTDNodeCopySystemID(_CFXMLDTDNodePtr node);
 void _CFXMLDTDNodeSetSystemID(_CFXMLDTDNodePtr node, const unsigned char* _Nullable systemID);
-CF_RETURNS_RETAINED CFStringRef _Nullable _CFXMLDTDNodeGetPublicID(_CFXMLDTDNodePtr node);
+CFStringRef _Nullable _CFXMLDTDNodeCopyPublicID(_CFXMLDTDNodePtr node);
 void _CFXMLDTDNodeSetPublicID(_CFXMLDTDNodePtr node, const unsigned char* _Nullable publicID);
 
+// Namespaces
+_CFXMLNodePtr _Nonnull * _Nullable _CFXMLNamespaces(_CFXMLNodePtr node, CFIndex* count);
+void _CFXMLSetNamespaces(_CFXMLNodePtr node, _CFXMLNodePtr _Nonnull * _Nullable nodes, CFIndex count);
+CFStringRef _Nullable _CFXMLNamespaceCopyValue(_CFXMLNodePtr node);
+void _CFXMLNamespaceSetValue(_CFXMLNodePtr node, const char* _Nullable value, int64_t length);
+CFStringRef _Nullable _CFXMLNamespaceCopyPrefix(_CFXMLNodePtr node);
+void _CFXMLNamespaceSetPrefix(_CFXMLNodePtr node, const char* _Nullable prefix, int64_t length);
+_CFXMLNodePtr _CFXMLNewNamespace(const char* name, const char* stringValue);
+void _CFXMLAddNamespace(_CFXMLNodePtr node, _CFXMLNodePtr nsNode);
+void _CFXMLRemoveNamespace(_CFXMLNodePtr node, const char* prefix);
+
 void _CFXMLFreeNode(_CFXMLNodePtr node);
 void _CFXMLFreeDocument(_CFXMLDocPtr doc);
 void _CFXMLFreeDTD(_CFXMLDTDPtr dtd);
diff --git a/Foundation.xcodeproj/project.pbxproj b/Foundation.xcodeproj/project.pbxproj
index 94d542d..d216523 100644
--- a/Foundation.xcodeproj/project.pbxproj
+++ b/Foundation.xcodeproj/project.pbxproj
@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		0383A1751D2E558A0052E5D1 /* TestNSStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0383A1741D2E558A0052E5D1 /* TestNSStream.swift */; };
+                03B6F5841F15F339004F25AF /* TestNSURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B6F5831F15F339004F25AF /* TestNSURLProtocol.swift */; };
 		1520469B1D8AEABE00D02E36 /* HTTPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1520469A1D8AEABE00D02E36 /* HTTPServer.swift */; };
 		159884921DCC877700E3314C /* TestNSHTTPCookieStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 159884911DCC877700E3314C /* TestNSHTTPCookieStorage.swift */; };
 		231503DB1D8AEE5D0061694D /* TestNSDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestNSDecimal.swift */; };
@@ -353,6 +354,7 @@
 		D51239DF1CD9DA0800D433EE /* CFSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D88E01BBC9B0300234F36 /* CFSocket.c */; };
 		D512D17C1CD883F00032E6A5 /* TestFileHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512D17B1CD883F00032E6A5 /* TestFileHandle.swift */; };
 		D5C40F331CDA1D460005690C /* TestNSOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C40F321CDA1D460005690C /* TestNSOperationQueue.swift */; };
+		DCA8120B1F046D13000D0C86 /* TestCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA8120A1F046D13000D0C86 /* TestCodable.swift */; };
 		E1A03F361C4828650023AF4D /* PropertyList-1.0.dtd in Resources */ = {isa = PBXBuildFile; fileRef = E1A03F351C4828650023AF4D /* PropertyList-1.0.dtd */; };
 		E1A03F381C482C730023AF4D /* NSXMLDTDTestData.xml in Resources */ = {isa = PBXBuildFile; fileRef = E1A03F371C482C730023AF4D /* NSXMLDTDTestData.xml */; };
 		E1A3726F1C31EBFB0023AF4D /* NSXMLDocumentTestData.xml in Resources */ = {isa = PBXBuildFile; fileRef = E1A3726E1C31EBFB0023AF4D /* NSXMLDocumentTestData.xml */; };
@@ -479,6 +481,7 @@
 
 /* Begin PBXFileReference section */
 		0383A1741D2E558A0052E5D1 /* TestNSStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSStream.swift; sourceTree = "<group>"; };
+                03B6F5831F15F339004F25AF /* TestNSURLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSURLProtocol.swift; sourceTree = "<group>"; };
 		1520469A1D8AEABE00D02E36 /* HTTPServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPServer.swift; sourceTree = "<group>"; };
 		159884911DCC877700E3314C /* TestNSHTTPCookieStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSHTTPCookieStorage.swift; sourceTree = "<group>"; };
 		22B9C1E01C165D7A00DECFF9 /* TestNSDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSDate.swift; sourceTree = "<group>"; };
@@ -820,6 +823,7 @@
 		D512D17B1CD883F00032E6A5 /* TestFileHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestFileHandle.swift; sourceTree = "<group>"; };
 		D5C40F321CDA1D460005690C /* TestNSOperationQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSOperationQueue.swift; sourceTree = "<group>"; };
 		D834F9931C31C4060023812A /* TestNSOrderedSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSOrderedSet.swift; sourceTree = "<group>"; };
+		DCA8120A1F046D13000D0C86 /* TestCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCodable.swift; sourceTree = "<group>"; };
 		DCDBB8321C1768AC00313299 /* TestNSData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSData.swift; sourceTree = "<group>"; };
 		E1A03F351C4828650023AF4D /* PropertyList-1.0.dtd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "PropertyList-1.0.dtd"; sourceTree = "<group>"; };
 		E1A03F371C482C730023AF4D /* NSXMLDTDTestData.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = NSXMLDTDTestData.xml; sourceTree = "<group>"; };
@@ -1421,8 +1425,7 @@
 				A058C2011E529CF100B07AA1 /* TestMassFormatter.swift */,
 				BF8E65301DC3B3CB005AB5C3 /* TestNotification.swift */,
 				3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */,
-				159884911DCC877700E3314C /* TestNSHTTPCookieStorage.swift */,
-				D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
+				DCA8120A1F046D13000D0C86 /* TestCodable.swift */,
 				C93559281C12C49F009FD6A9 /* TestNSAffineTransform.swift */,
 				EA66F63C1BF1619600136161 /* TestNSArray.swift */,
 				294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */,
@@ -1484,6 +1487,7 @@
 				CC5249BF1D341D23007CB54D /* TestUnitConverter.swift */,
 				D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
 				5B6F17961C48631C00935030 /* TestUtils.swift */,
+                                03B6F5831F15F339004F25AF /* TestNSURLProtocol.swift */,
 			);
 			name = Tests;
 			sourceTree = "<group>";
@@ -2372,6 +2376,7 @@
 				BF8E65311DC3B3CB005AB5C3 /* TestNotification.swift in Sources */,
 				63DCE9D41EAA432400E9CB02 /* TestISO8601DateFormatter.swift in Sources */,
 				EA01AAEC1DA839C4008F4E07 /* TestProgress.swift in Sources */,
+                                03B6F5841F15F339004F25AF /* TestNSURLProtocol.swift in Sources */,
 				5B13B3411C582D4C00651CE2 /* TestNSRegularExpression.swift in Sources */,
 				5B13B3491C582D4C00651CE2 /* TestNSTimeZone.swift in Sources */,
 				5B13B34B1C582D4C00651CE2 /* TestNSURLRequest.swift in Sources */,
@@ -2426,6 +2431,7 @@
 				5B13B3271C582D4C00651CE2 /* TestNSArray.swift in Sources */,
 				5B13B3461C582D4C00651CE2 /* TestProcess.swift in Sources */,
 				555683BD1C1250E70041D4C6 /* TestNSUserDefaults.swift in Sources */,
+				DCA8120B1F046D13000D0C86 /* TestCodable.swift in Sources */,
 				7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/Foundation/CGFloat.swift b/Foundation/CGFloat.swift
index 03371f3..904600d 100644
--- a/Foundation/CGFloat.swift
+++ b/Foundation/CGFloat.swift
@@ -949,3 +949,35 @@
         return native._cVarArgAlignment
     }
 }
+
+extension CGFloat : Codable {
+    @_transparent
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.singleValueContainer()
+        do {
+            self.native = try container.decode(NativeType.self)
+        } catch DecodingError.typeMismatch(let type, let context) {
+            // We may have encoded as a different type on a different platform. A
+            // strict fixed-format decoder may disallow a conversion, so let's try the
+            // other type.
+            do {
+                if NativeType.self == Float.self {
+                    self.native = NativeType(try container.decode(Double.self))
+                } else {
+                    self.native = NativeType(try container.decode(Float.self))
+                }
+            } catch {
+                // Failed to decode as the other type, too. This is neither a Float nor
+                // a Double. Throw the old error; we don't want to clobber the original
+                // info.
+                throw DecodingError.typeMismatch(type, context)
+            }
+        }
+    }
+    
+    @_transparent
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.singleValueContainer()
+        try container.encode(self.native)
+    }
+}
diff --git a/Foundation/CharacterSet.swift b/Foundation/CharacterSet.swift
index bb346f7..84fa74c 100644
--- a/Foundation/CharacterSet.swift
+++ b/Foundation/CharacterSet.swift
@@ -1,4 +1,4 @@
- //===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -13,7 +13,7 @@
 private func _utfRangeToNSRange(_ inRange : Range<UnicodeScalar>) -> NSRange {
     return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value))
 }
- 
+
 private func _utfRangeToNSRange(_ inRange : ClosedRange<UnicodeScalar>) -> NSRange {
     return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value + 1))
 }
@@ -57,9 +57,9 @@
     deinit {
         releaseWrappedObject()
     }
-
-
-   override func copy(with zone: NSZone? = nil) -> Any {
+    
+    
+    override func copy(with zone: NSZone? = nil) -> Any {
         return _mapUnmanaged { $0.copy(with: zone) }
     }
     
@@ -74,26 +74,32 @@
     override var bitmapRepresentation: Data {
         return _mapUnmanaged { $0.bitmapRepresentation }
     }
-
+    
     override var inverted : CharacterSet {
         return _mapUnmanaged { $0.inverted }
     }
-
+    
     override func hasMemberInPlane(_ thePlane: UInt8) -> Bool {
         return _mapUnmanaged {$0.hasMemberInPlane(thePlane) }
     }
-
+    
     override func characterIsMember(_ member: unichar) -> Bool {
         return _mapUnmanaged { $0.characterIsMember(member) }
     }
-
+    
     override func longCharacterIsMember(_ member: UInt32) -> Bool {
         return _mapUnmanaged { $0.longCharacterIsMember(member) }
     }
-
+    
     override func isSuperset(of other: CharacterSet) -> Bool {
         return _mapUnmanaged { $0.isSuperset(of: other) }
     }
+
+    override var _cfObject: CFType {
+        // We cannot inherit super's unsafeBitCast(self, to: CFType.self) here, because layout of _SwiftNSCharacterSet
+        // is not compatible with CFCharacterSet. We need to bitcast the underlying NSCharacterSet instead.
+        return _mapUnmanaged { unsafeBitCast($0, to: CFType.self) }
+    }
 }
 
 /**
@@ -367,7 +373,7 @@
     // -----
     // MARK: -
     // MARK: SetAlgebraType
-
+    
     /// Insert a `UnicodeScalar` representation of a character into the `CharacterSet`.
     ///
     /// `UnicodeScalar` values are available on `Swift.String.UnicodeScalarView`.
@@ -441,17 +447,17 @@
             $0.formIntersection(with: other)
         }
     }
-
+    
     /// Returns a `CharacterSet` created by removing elements in `other` from `self`.
     public func subtracting(_ other: CharacterSet) -> CharacterSet {
         return intersection(other.inverted)
     }
-
+    
     /// Sets the value to a `CharacterSet` created by removing elements in `other` from `self`.
     public mutating func subtract(_ other: CharacterSet) {
         self = subtracting(other)
     }
-
+    
     /// Returns an exclusive or of the `CharacterSet` with another `CharacterSet`.
     public func symmetricDifference(_ other: CharacterSet) -> CharacterSet {
         return union(other).subtracting(intersection(other))
@@ -466,16 +472,16 @@
     public func isSuperset(of other: CharacterSet) -> Bool {
         return _mapUnmanaged { $0.isSuperset(of: other) }
     }
-
+    
     /// Returns true if the two `CharacterSet`s are equal.
     public static func ==(lhs : CharacterSet, rhs: CharacterSet) -> Bool {
-        return lhs._wrapped.isEqual(rhs._bridgeToObjectiveC()) // TODO: mlehew - as  NSCharacterSet
+        return lhs._mapUnmanaged { $0.isEqual(rhs) }
     }
 }
 
 
 // MARK: Objective-C Bridging
- extension CharacterSet : _ObjectTypeBridgeable {
+extension CharacterSet : _ObjectTypeBridgeable {
     public static func _isBridgedToObjectiveC() -> Bool {
         return true
     }
@@ -503,3 +509,20 @@
     }
     
 }
+
+extension CharacterSet : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case bitmap
+    }
+    
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        let bitmap = try container.decode(Data.self, forKey: .bitmap)
+        self.init(bitmapRepresentation: bitmap)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(self.bitmapRepresentation, forKey: .bitmap)
+    }
+}
diff --git a/Foundation/Codable.swift b/Foundation/Codable.swift
index 06bdc21..3e34692 100644
--- a/Foundation/Codable.swift
+++ b/Foundation/Codable.swift
@@ -8,64 +8,6 @@
 //
 
 //===----------------------------------------------------------------------===//
-// Errors
-//===----------------------------------------------------------------------===//
-
-// Adding the following extensions to EncodingError and DecodingError allows them to bridge to NSErrors implicitly.
-
-fileprivate let NSCodingPathErrorKey = "NSCodingPath"
-fileprivate let NSDebugDescriptionErrorKey = "NSDebugDescription"
-
-extension EncodingError : CustomNSError {
-    public static var errorDomain: String = NSCocoaErrorDomain
-
-    public var errorCode: Int {
-        switch self {
-        case .invalidValue(_, _): return CocoaError.coderInvalidValue.rawValue
-        }
-    }
-
-    public var errorUserInfo: [String : Any] {
-        let context: Context
-        switch self {
-        case .invalidValue(_, let c): context = c
-        }
-
-        return [NSCodingPathErrorKey: context.codingPath,
-                NSDebugDescriptionErrorKey: context.debugDescription]
-    }
-}
-
-extension DecodingError : CustomNSError {
-    public static var errorDomain: String = NSCocoaErrorDomain
-
-    public var errorCode: Int {
-        switch self {
-        case .valueNotFound(_, _): fallthrough
-        case .keyNotFound(_, _):
-            return CocoaError.coderValueNotFound.rawValue
-
-        case .typeMismatch(_, _): fallthrough
-        case .dataCorrupted(_):
-            return CocoaError.coderReadCorrupt.rawValue
-        }
-    }
-
-    public var errorUserInfo: [String : Any] {
-        let context: Context
-        switch self {
-        case .typeMismatch(_, let c): context = c
-        case .valueNotFound(_, let c): context = c
-        case .keyNotFound(_, let c): context = c
-        case .dataCorrupted(let c): context = c
-        }
-
-        return [NSCodingPathErrorKey: context.codingPath,
-                NSDebugDescriptionErrorKey: context.debugDescription]
-    }
-}
-
-//===----------------------------------------------------------------------===//
 // Error Utilities
 //===----------------------------------------------------------------------===//
 
@@ -76,7 +18,7 @@
     /// - parameter expectation: The type expected to be encountered.
     /// - parameter reality: The value that was encountered instead of the expected type.
     /// - returns: A `DecodingError` with the appropriate path and debug description.
-    internal static func _typeMismatch(at path: [CodingKey?], expectation: Any.Type, reality: Any) -> DecodingError {
+    internal static func _typeMismatch(at path: [CodingKey], expectation: Any.Type, reality: Any) -> DecodingError {
         let description = "Expected to decode \(expectation) but found \(_typeDescription(of: reality)) instead."
         return .typeMismatch(expectation, Context(codingPath: path, debugDescription: description))
     }
diff --git a/Foundation/Data.swift b/Foundation/Data.swift
index 5fe69e2..aa63929 100644
--- a/Foundation/Data.swift
+++ b/Foundation/Data.swift
@@ -1514,7 +1514,6 @@
     @inline(__always)
     public func subdata(in range: Range<Index>) -> Data {
         _validateRange(range)
-        let length = count
         if count == 0 {
             return Data()
         }
diff --git a/Foundation/ExtraStringAPIs.swift b/Foundation/ExtraStringAPIs.swift
index 792c2f6..2f5d4f1 100644
--- a/Foundation/ExtraStringAPIs.swift
+++ b/Foundation/ExtraStringAPIs.swift
@@ -17,18 +17,16 @@
     /// Construct from an integer offset.
     public init(_ offset: Int) {
         _precondition(offset >= 0, "Negative UTF16 index offset not allowed")
-        self.init(_offset: offset)
+        self.init(encodedOffset: offset)
     }
     
     public func distance(to other: String.UTF16View.Index) -> Int {
-        return _offset.distance(to: other._offset)
+        return encodedOffset.distance(to: other.encodedOffset)
     }
     
     public func advanced(by n: Int) -> String.UTF16View.Index {
-        return String.UTF16View.Index(_offset.advanced(by: n))
+        return String.UTF16View.Index(encodedOffset.advanced(by: n))
     }
 }
 
-extension String.UTF16View : RandomAccessCollection {}
-extension String.UTF16View.Indices : RandomAccessCollection {}
 
diff --git a/Foundation/FileHandle.swift b/Foundation/FileHandle.swift
index 645dc5d..28bf722 100644
--- a/Foundation/FileHandle.swift
+++ b/Foundation/FileHandle.swift
@@ -76,7 +76,7 @@
                 fatalError("Unable to fetch current file offset")
             }
             if off_t(statbuf.st_size) > offset {
-                var remaining = size_t(statbuf.st_size - offset)
+                var remaining = size_t(off_t(statbuf.st_size) - offset)
                 remaining = min(remaining, size_t(length))
                 
                 dynamicBuffer = malloc(remaining)
diff --git a/Foundation/FileManager.swift b/Foundation/FileManager.swift
index ba4649f..c2f1417 100644
--- a/Foundation/FileManager.swift
+++ b/Foundation/FileManager.swift
@@ -624,9 +624,12 @@
         }
     }
     
-    open func createFile(atPath path: String, contents data: Data?, attributes attr: [String : Any]? = [:]) -> Bool {
+    open func createFile(atPath path: String, contents data: Data?, attributes attr: [FileAttributeKey : Any]? = nil) -> Bool {
         do {
             try (data ?? Data()).write(to: URL(fileURLWithPath: path), options: .atomic)
+            if let attr = attr {
+                try self.setAttributes(attr, ofItemAtPath: path)
+            }
             return true
         } catch _ {
             return false
diff --git a/Foundation/IndexPath.swift b/Foundation/IndexPath.swift
index b85aaf6..748c03a 100644
--- a/Foundation/IndexPath.swift
+++ b/Foundation/IndexPath.swift
@@ -851,4 +851,3 @@
         }
     }
 }
-
diff --git a/Foundation/JSONEncoder.swift b/Foundation/JSONEncoder.swift
index c6f09e0..59a3844 100644
--- a/Foundation/JSONEncoder.swift
+++ b/Foundation/JSONEncoder.swift
@@ -1,11 +1,16 @@
+//===----------------------------------------------------------------------===//
+//
 // This source file is part of the Swift.org open source project
 //
 // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
-// See http://swift.org/LICENSE.txt for license information
-// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
+//===----------------------------------------------------------------------===//
+
+import CoreFoundation
 
 //===----------------------------------------------------------------------===//
 // JSON Encoder
@@ -138,7 +143,7 @@
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) encoded as string JSON fragment."))
         }
 
-        var writingOptions = JSONSerialization.WritingOptions(rawValue: self.outputFormatting.rawValue)
+        let writingOptions = JSONSerialization.WritingOptions(rawValue: self.outputFormatting.rawValue)
         return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)
     }
 }
@@ -149,23 +154,23 @@
     // MARK: Properties
 
     /// The encoder's storage.
-    var storage: _JSONEncodingStorage
+    fileprivate var storage: _JSONEncodingStorage
 
     /// Options set on the top-level encoder.
-    let options: JSONEncoder._Options
+    fileprivate let options: JSONEncoder._Options
 
     /// The path to the current point in encoding.
-    var codingPath: [CodingKey?]
+    public var codingPath: [CodingKey]
 
     /// Contextual user-provided information for use during encoding.
-    var userInfo: [CodingUserInfoKey : Any] {
+    public var userInfo: [CodingUserInfoKey : Any] {
         return self.options.userInfo
     }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given top-level encoder options.
-    init(options: JSONEncoder._Options, codingPath: [CodingKey?] = []) {
+    fileprivate init(options: JSONEncoder._Options, codingPath: [CodingKey] = []) {
         self.options = options
         self.storage = _JSONEncodingStorage()
         self.codingPath = codingPath
@@ -177,7 +182,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -187,7 +192,7 @@
     /// Returns whether a new element can be encoded at this coding path.
     ///
     /// `true` if an element has not yet been encoded at this coding path; `false` otherwise.
-    var canEncodeNewElement: Bool {
+    fileprivate var canEncodeNewValue: Bool {
         // Every time a new value gets encoded, the key it's encoded for is pushed onto the coding path (even if it's a nil key from an unkeyed container).
         // At the same time, every time a container is requested, a new value gets pushed onto the storage stack.
         // If there are more values on the storage stack than on the coding path, it means the value is requesting more than one container, which violates the precondition.
@@ -197,39 +202,43 @@
         return self.storage.count == self.codingPath.count
     }
 
-    /// Asserts that a new container can be requested at this coding path.
-    /// `preconditionFailure()`s if one cannot be requested.
-    func assertCanRequestNewContainer() {
-        guard self.canEncodeNewElement else {
-            let previousContainerType: String
-            if self.storage.containers.last is NSDictionary {
-                previousContainerType = "keyed"
-            } else if self.storage.containers.last is NSArray {
-                previousContainerType = "unkeyed"
-            } else {
-                previousContainerType = "single value"
+    // MARK: - Encoder Methods
+    public func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
+        // If an existing keyed container was already requested, return that one.
+        let topContainer: NSMutableDictionary
+        if self.canEncodeNewValue {
+            // We haven't yet pushed a container at this level; do so here.
+            topContainer = self.storage.pushKeyedContainer()
+        } else {
+            guard let container = self.storage.containers.last as? NSMutableDictionary else {
+                preconditionFailure("Attempt to push new keyed encoding container when already previously encoded at this path.")
             }
 
-            preconditionFailure("Attempt to encode with new container when already encoded with \(previousContainerType) container.")
+            topContainer = container
         }
-    }
 
-    // MARK: - Encoder Methods
-    func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
-        assertCanRequestNewContainer()
-        let topContainer = self.storage.pushKeyedContainer()
         let container = _JSONKeyedEncodingContainer<Key>(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
         return KeyedEncodingContainer(container)
     }
 
-    func unkeyedContainer() -> UnkeyedEncodingContainer {
-        assertCanRequestNewContainer()
-        let topContainer = self.storage.pushUnkeyedContainer()
+    public func unkeyedContainer() -> UnkeyedEncodingContainer {
+        // If an existing unkeyed container was already requested, return that one.
+        let topContainer: NSMutableArray
+        if self.canEncodeNewValue {
+            // We haven't yet pushed a container at this level; do so here.
+            topContainer = self.storage.pushUnkeyedContainer()
+        } else {
+            guard let container = self.storage.containers.last as? NSMutableArray else {
+                preconditionFailure("Attempt to push new unkeyed encoding container when already previously encoded at this path.")
+            }
+
+            topContainer = container
+        }
+
         return _JSONUnkeyedEncodingContainer(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
     }
 
-    func singleValueContainer() -> SingleValueEncodingContainer {
-        assertCanRequestNewContainer()
+    public func singleValueContainer() -> SingleValueEncodingContainer {
         return self
     }
 }
@@ -241,36 +250,36 @@
 
     /// The container stack.
     /// Elements may be any one of the JSON types (NSNull, NSNumber, NSString, NSArray, NSDictionary).
-    private(set) var containers: [NSObject] = []
+    private(set) fileprivate var containers: [NSObject] = []
 
     // MARK: - Initialization
 
     /// Initializes `self` with no containers.
-    init() {}
+    fileprivate init() {}
 
     // MARK: - Modifying the Stack
 
-    var count: Int {
+    fileprivate var count: Int {
         return self.containers.count
     }
 
-    mutating func pushKeyedContainer() -> NSMutableDictionary {
+    fileprivate mutating func pushKeyedContainer() -> NSMutableDictionary {
         let dictionary = NSMutableDictionary()
         self.containers.append(dictionary)
         return dictionary
     }
 
-    mutating func pushUnkeyedContainer() -> NSMutableArray {
+    fileprivate mutating func pushUnkeyedContainer() -> NSMutableArray {
         let array = NSMutableArray()
         self.containers.append(array)
         return array
     }
 
-    mutating func push(container: NSObject) {
+    fileprivate mutating func push(container: NSObject) {
         self.containers.append(container)
     }
 
-    mutating func popContainer() -> NSObject {
+    fileprivate mutating func popContainer() -> NSObject {
         precondition(self.containers.count > 0, "Empty container stack.")
         return self.containers.popLast()!
     }
@@ -284,18 +293,18 @@
     // MARK: Properties
 
     /// A reference to the encoder we're writing to.
-    let encoder: _JSONEncoder
+    private let encoder: _JSONEncoder
 
     /// A reference to the container we're writing to.
-    let container: NSMutableDictionary
+    private let container: NSMutableDictionary
 
     /// The path of coding keys taken to get to this point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey]
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given references.
-    init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableDictionary) {
+    fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey], wrapping container: NSMutableDictionary) {
         self.encoder = encoder
         self.codingPath = codingPath
         self.container = container
@@ -307,7 +316,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate mutating func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -316,40 +325,41 @@
 
     // MARK: - KeyedEncodingContainerProtocol Methods
 
-    mutating func encode(_ value: Bool, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: Int, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: Int8, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: Int16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: Int32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: Int64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt8, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
-    mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encodeNil(forKey key: Key)               throws { self.container[key.stringValue._bridgeToObjectiveC()] = NSNull() }
+    public mutating func encode(_ value: Bool, forKey key: Key)   throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int, forKey key: Key)    throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int8, forKey key: Key)   throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int16, forKey key: Key)  throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int32, forKey key: Key)  throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int64, forKey key: Key)  throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt, forKey key: Key)   throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt8, forKey key: Key)  throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+    public mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
 
-    mutating func encode(_ value: Float, forKey key: Key)  throws {
+    public mutating func encode(_ value: Float, forKey key: Key)  throws {
         // Since the float may be invalid and throw, the coding path needs to contain this key.
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue._bridgeToObjectiveC()] = try self.encoder.box(value)
         }
     }
 
-    mutating func encode(_ value: Double, forKey key: Key) throws {
+    public mutating func encode(_ value: Double, forKey key: Key) throws {
         // Since the double may be invalid and throw, the coding path needs to contain this key.
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue._bridgeToObjectiveC()] = try self.encoder.box(value)
         }
     }
 
-    mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
+    public mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue._bridgeToObjectiveC()] = try self.encoder.box(value)
         }
     }
 
-    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
         let dictionary = NSMutableDictionary()
         self.container[key.stringValue._bridgeToObjectiveC()] = dictionary
 
@@ -359,7 +369,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+    public mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
         let array = NSMutableArray()
         self.container[key.stringValue._bridgeToObjectiveC()] = array
 
@@ -368,11 +378,11 @@
         }
     }
 
-    mutating func superEncoder() -> Encoder {
-        return _JSONReferencingEncoder(referencing: self.encoder, at: _JSONSuperKey.super, wrapping: self.container)
+    public mutating func superEncoder() -> Encoder {
+        return _JSONReferencingEncoder(referencing: self.encoder, at: _JSONKey.super, wrapping: self.container)
     }
 
-    mutating func superEncoder(forKey key: Key) -> Encoder {
+    public mutating func superEncoder(forKey key: Key) -> Encoder {
         return _JSONReferencingEncoder(referencing: self.encoder, at: key, wrapping: self.container)
     }
 }
@@ -381,18 +391,23 @@
     // MARK: Properties
 
     /// A reference to the encoder we're writing to.
-    let encoder: _JSONEncoder
+    private let encoder: _JSONEncoder
 
     /// A reference to the container we're writing to.
-    let container: NSMutableArray
+    private let container: NSMutableArray
 
     /// The path of coding keys taken to get to this point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey]
+
+    /// The number of elements encoded into the container.
+    public var count: Int {
+        return self.container.count
+    }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given references.
-    init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableArray) {
+    fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey], wrapping container: NSMutableArray) {
         self.encoder = encoder
         self.codingPath = codingPath
         self.container = container
@@ -404,7 +419,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate mutating func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -413,164 +428,150 @@
 
     // MARK: - UnkeyedEncodingContainer Methods
 
-    mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encodeNil()             throws { self.container.add(NSNull()) }
+    public mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
 
-    mutating func encode(_ value: Float)  throws {
+    public mutating func encode(_ value: Float)  throws {
         // Since the float may be invalid and throw, the coding path needs to contain this key.
-        try self.encoder.with(pushedKey: nil) {
+        try self.encoder.with(pushedKey: _JSONKey(index: self.count)) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func encode(_ value: Double) throws {
+    public mutating func encode(_ value: Double) throws {
         // Since the double may be invalid and throw, the coding path needs to contain this key.
-        try self.encoder.with(pushedKey: nil) {
+        try self.encoder.with(pushedKey: _JSONKey(index: self.count)) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func encode<T : Encodable>(_ value: T) throws {
-        try self.encoder.with(pushedKey: nil) {
+    public mutating func encode<T : Encodable>(_ value: T) throws {
+        try self.encoder.with(pushedKey: _JSONKey(index: self.count)) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
         let dictionary = NSMutableDictionary()
         self.container.add(dictionary)
 
-        return self.with(pushedKey: nil) {
+        // self.count - 1 to accommodate the fact that we just pushed a container.
+        return self.with(pushedKey: _JSONKey(index: self.count - 1)) {
             let container = _JSONKeyedEncodingContainer<NestedKey>(referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary)
             return KeyedEncodingContainer(container)
         }
     }
 
-    mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
+    public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
         let array = NSMutableArray()
         self.container.add(array)
 
-        return self.with(pushedKey: nil) {
+        // self.count - 1 to accommodate the fact that we just pushed a container.
+        return self.with(pushedKey: _JSONKey(index: self.count - 1)) {
             return _JSONUnkeyedEncodingContainer(referencing: self.encoder, codingPath: self.codingPath, wrapping: array)
         }
     }
 
-    mutating func superEncoder() -> Encoder {
+    public mutating func superEncoder() -> Encoder {
         return _JSONReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container)
     }
 }
 
 extension _JSONEncoder : SingleValueEncodingContainer {
-    // MARK: - Utility Methods
-
-    /// Asserts that a single value can be encoded at the current coding path (i.e. that one has not already been encoded through this container).
-    /// `preconditionFailure()`s if one cannot be encoded.
-    ///
-    /// This is similar to assertCanRequestNewContainer above.
-    func assertCanEncodeSingleValue() {
-        guard self.canEncodeNewElement else {
-            let previousContainerType: String
-            if self.storage.containers.last is NSDictionary {
-                previousContainerType = "keyed"
-            } else if self.storage.containers.last is NSArray {
-                previousContainerType = "unkeyed"
-            } else {
-                preconditionFailure("Attempt to encode multiple values in a single value container.")
-            }
-
-            preconditionFailure("Attempt to encode with new container when already encoded with \(previousContainerType) container.")
-        }
-    }
-
     // MARK: - SingleValueEncodingContainer Methods
 
-    func encodeNil() throws {
-        assertCanEncodeSingleValue()
+    fileprivate func assertCanEncodeNewValue() {
+        precondition(self.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
+    }
+
+    public func encodeNil() throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: NSNull())
     }
 
-    func encode(_ value: Bool) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Bool) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Int) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int8) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Int8) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int16) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Int16) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int32) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Int32) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int64) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Int64) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: UInt) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt8) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: UInt8) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt16) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: UInt16) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt32) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: UInt32) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt64) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: UInt64) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: String) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: String) throws {
+        assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Float) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Float) throws {
+        assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Double) throws {
-        assertCanEncodeSingleValue()
+    public func encode(_ value: Double) throws {
+        assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
 
-    func encode<T : Encodable>(_ value: T) throws {
-        assertCanEncodeSingleValue()
+    public func encode<T : Encodable>(_ value: T) throws {
+        assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
 }
@@ -597,7 +598,7 @@
             guard case let .convertToString(positiveInfinity: posInfString,
                                             negativeInfinity: negInfString,
                                             nan: nanString) = self.options.nonConformingFloatEncodingStrategy else {
-                                                throw EncodingError._invalidFloatingPointValue(float, at: codingPath)
+                throw EncodingError._invalidFloatingPointValue(float, at: codingPath)
             }
 
             if float == Float.infinity {
@@ -617,7 +618,7 @@
             guard case let .convertToString(positiveInfinity: posInfString,
                                             negativeInfinity: negInfString,
                                             nan: nanString) = self.options.nonConformingFloatEncodingStrategy else {
-                                                throw EncodingError._invalidFloatingPointValue(double, at: codingPath)
+                throw EncodingError._invalidFloatingPointValue(double, at: codingPath)
             }
 
             if double == Double.infinity {
@@ -698,6 +699,11 @@
         } else if T.self == URL.self {
             // Encode URLs as single strings.
             return self.box((value as! URL).absoluteString)
+        } else if T.self == Decimal.self {
+            // On Darwin we get ((value as! Decimal) as NSDecimalNumber) since JSONSerialization can consume NSDecimalNumber values.
+            // FIXME: Attempt to create a Decimal value if JSONSerialization on Linux consume one.
+            let doubleValue = (value as! Decimal).doubleValue
+            return try self.box(doubleValue)
         }
 
         // The value should request a container from the _JSONEncoder.
@@ -722,7 +728,7 @@
     // MARK: Reference types.
 
     /// The type of container we're referencing.
-    enum Reference {
+    private enum Reference {
         /// Referencing a specific index in an array container.
         case array(NSMutableArray, Int)
 
@@ -733,24 +739,24 @@
     // MARK: - Properties
 
     /// The encoder we're referencing.
-    let encoder: _JSONEncoder
+    fileprivate let encoder: _JSONEncoder
 
     /// The container reference itself.
-    let reference: Reference
+    private let reference: Reference
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given array container in the given encoder.
-    init(referencing encoder: _JSONEncoder, at index: Int, wrapping array: NSMutableArray) {
+    fileprivate init(referencing encoder: _JSONEncoder, at index: Int, wrapping array: NSMutableArray) {
         self.encoder = encoder
         self.reference = .array(array, index)
         super.init(options: encoder.options, codingPath: encoder.codingPath)
 
-        self.codingPath.append(nil)
+        self.codingPath.append(_JSONKey(index: index))
     }
 
     /// Initializes `self` by referencing the given dictionary container in the given encoder.
-    init(referencing encoder: _JSONEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
+    fileprivate init(referencing encoder: _JSONEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
         self.encoder = encoder
         self.reference = .dictionary(dictionary, key.stringValue)
         super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -760,7 +766,7 @@
 
     // MARK: - Coding Path Operations
 
-    override var canEncodeNewElement: Bool {
+    fileprivate override var canEncodeNewValue: Bool {
         // With a regular encoder, the storage and coding path grow together.
         // A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
         // We have to take this into account.
@@ -891,23 +897,23 @@
     // MARK: Properties
 
     /// The decoder's storage.
-    var storage: _JSONDecodingStorage
+    fileprivate var storage: _JSONDecodingStorage
 
     /// Options set on the top-level decoder.
-    let options: JSONDecoder._Options
+    fileprivate let options: JSONDecoder._Options
 
     /// The path to the current point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey]
 
     /// Contextual user-provided information for use during encoding.
-    var userInfo: [CodingUserInfoKey : Any] {
+    public var userInfo: [CodingUserInfoKey : Any] {
         return self.options.userInfo
     }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given top-level container and options.
-    init(referencing container: Any, at codingPath: [CodingKey?] = [], options: JSONDecoder._Options) {
+    fileprivate init(referencing container: Any, at codingPath: [CodingKey] = [], options: JSONDecoder._Options) {
         self.storage = _JSONDecodingStorage()
         self.storage.push(container: container)
         self.codingPath = codingPath
@@ -920,7 +926,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -929,7 +935,7 @@
 
     // MARK: - Decoder Methods
 
-    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
+    public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
         guard !(self.storage.topContainer is NSNull) else {
             throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
                                               DecodingError.Context(codingPath: self.codingPath,
@@ -944,7 +950,7 @@
         return KeyedDecodingContainer(container)
     }
 
-    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
+    public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
         guard !(self.storage.topContainer is NSNull) else {
             throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                               DecodingError.Context(codingPath: self.codingPath,
@@ -958,7 +964,7 @@
         return _JSONUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
     }
 
-    func singleValueContainer() throws -> SingleValueDecodingContainer {
+    public func singleValueContainer() throws -> SingleValueDecodingContainer {
         return self
     }
 }
@@ -970,29 +976,29 @@
 
     /// The container stack.
     /// Elements may be any one of the JSON types (NSNull, NSNumber, String, Array, [String : Any]).
-    private(set) var containers: [Any] = []
+    private(set) fileprivate var containers: [Any] = []
 
     // MARK: - Initialization
 
     /// Initializes `self` with no containers.
-    init() {}
+    fileprivate init() {}
 
     // MARK: - Modifying the Stack
 
-    var count: Int {
+    fileprivate var count: Int {
         return self.containers.count
     }
 
-    var topContainer: Any {
+    fileprivate var topContainer: Any {
         precondition(self.containers.count > 0, "Empty container stack.")
         return self.containers.last!
     }
 
-    mutating func push(container: Any) {
+    fileprivate mutating func push(container: Any) {
         self.containers.append(container)
     }
 
-    mutating func popContainer() {
+    fileprivate mutating func popContainer() {
         precondition(self.containers.count > 0, "Empty container stack.")
         self.containers.removeLast()
     }
@@ -1006,18 +1012,18 @@
     // MARK: Properties
 
     /// A reference to the decoder we're reading from.
-    let decoder: _JSONDecoder
+    private let decoder: _JSONDecoder
 
     /// A reference to the container we're reading from.
-    let container: [String : Any]
+    private let container: [String : Any]
 
     /// The path of coding keys taken to get to this point in decoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey]
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given decoder and container.
-    init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
+    fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
         self.decoder = decoder
         self.container = container
         self.codingPath = decoder.codingPath
@@ -1025,111 +1031,233 @@
 
     // MARK: - KeyedDecodingContainerProtocol Methods
 
-    var allKeys: [Key] {
+    public var allKeys: [Key] {
         return self.container.keys.flatMap { Key(stringValue: $0) }
     }
 
-    func contains(_ key: Key) -> Bool {
+    public func contains(_ key: Key) -> Bool {
         return self.container[key.stringValue] != nil
     }
 
-    func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
+    public func decodeNil(forKey key: Key) throws -> Bool {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
+        return entry is NSNull
+    }
+
+    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Bool.self)
+            guard let value = try self.decoder.unbox(entry, as: Bool.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
+    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int.self)
+            guard let value = try self.decoder.unbox(entry, as: Int.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
+    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int8.self)
+            guard let value = try self.decoder.unbox(entry, as: Int8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
+    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int16.self)
+            guard let value = try self.decoder.unbox(entry, as: Int16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
+    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int32.self)
+            guard let value = try self.decoder.unbox(entry, as: Int32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
+    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int64.self)
+            guard let value = try self.decoder.unbox(entry, as: Int64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
+    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
+    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt8.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
+    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt16.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
+    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt32.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
+    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt64.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
+    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Float.self)
+            guard let value = try self.decoder.unbox(entry, as: Float.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
+    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Double.self)
+            guard let value = try self.decoder.unbox(entry, as: Double.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
+    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: String.self)
+            guard let value = try self.decoder.unbox(entry, as: String.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Data.Type, forKey key: Key) throws -> Data? {
+    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Data.self)
+            guard let value = try self.decoder.unbox(entry, as: T.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T? {
-        return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: T.self)
-        }
-    }
-
-    func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
+    public func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
         return try self.decoder.with(pushedKey: key) {
             guard let value = self.container[key.stringValue] else {
                 throw DecodingError.keyNotFound(key,
@@ -1146,7 +1274,7 @@
         }
     }
 
-    func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
+    public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
         return try self.decoder.with(pushedKey: key) {
             guard let value = self.container[key.stringValue] else {
                 throw DecodingError.keyNotFound(key,
@@ -1162,23 +1290,18 @@
         }
     }
 
-    func _superDecoder(forKey key: CodingKey) throws -> Decoder {
-        return try self.decoder.with(pushedKey: key) {
-            guard let value = self.container[key.stringValue] else {
-                throw DecodingError.keyNotFound(key,
-                                                DecodingError.Context(codingPath: self.codingPath,
-                                                                      debugDescription: "Cannot get superDecoder() -- no value found for key \"\(key.stringValue)\""))
-            }
-
+    private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
+        return self.decoder.with(pushedKey: key) {
+            let value: Any = self.container[key.stringValue] ?? NSNull()
             return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
         }
     }
 
-    func superDecoder() throws -> Decoder {
-        return try _superDecoder(forKey: _JSONSuperKey.super)
+    public func superDecoder() throws -> Decoder {
+        return try _superDecoder(forKey: _JSONKey.super)
     }
 
-    func superDecoder(forKey key: Key) throws -> Decoder {
+    public func superDecoder(forKey key: Key) throws -> Decoder {
         return try _superDecoder(forKey: key)
     }
 }
@@ -1187,21 +1310,21 @@
     // MARK: Properties
 
     /// A reference to the decoder we're reading from.
-    let decoder: _JSONDecoder
+    private let decoder: _JSONDecoder
 
     /// A reference to the container we're reading from.
-    let container: [Any]
+    private let container: [Any]
 
     /// The path of coding keys taken to get to this point in decoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey]
 
     /// The index of the element we're about to decode.
-    var currentIndex: Int
+    private(set) public var currentIndex: Int
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given decoder and container.
-    init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
+    fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
         self.decoder = decoder
         self.container = container
         self.codingPath = decoder.codingPath
@@ -1210,176 +1333,254 @@
 
     // MARK: - UnkeyedDecodingContainer Methods
 
-    var count: Int? {
+    public var count: Int? {
         return self.container.count
     }
 
-    var isAtEnd: Bool {
+    public var isAtEnd: Bool {
         return self.currentIndex >= self.count!
     }
 
-    mutating func decodeIfPresent(_ type: Bool.Type) throws -> Bool? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decodeNil() throws -> Bool {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self)
+        if self.container[self.currentIndex] is NSNull {
+            self.currentIndex += 1
+            return true
+        } else {
+            return false
+        }
+    }
+
+    public mutating func decode(_ type: Bool.Type) throws -> Bool {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
+
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int.Type) throws -> Int? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int.Type) throws -> Int {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int8.Type) throws -> Int8? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int8.Type) throws -> Int8 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int16.Type) throws -> Int16? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int16.Type) throws -> Int16 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int32.Type) throws -> Int32? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int32.Type) throws -> Int32 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int64.Type) throws -> Int64? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int64.Type) throws -> Int64 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt.Type) throws -> UInt? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt.Type) throws -> UInt {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt8.Type) throws -> UInt8? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt16.Type) throws -> UInt16? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt32.Type) throws -> UInt32? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt64.Type) throws -> UInt64? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Float.Type) throws -> Float? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Float.Type) throws -> Float {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Double.Type) throws -> Double? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Double.Type) throws -> Double {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: String.Type) throws -> String? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: String.Type) throws -> String {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Data.Type) throws -> Data? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
+        }
 
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Data.self)
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent<T : Decodable>(_ type: T.Type) throws -> T? {
-        guard !self.isAtEnd else { return nil }
-
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self)
-            self.currentIndex += 1
-            return decoded
-        }
-    }
-
-    mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
-        return try self.decoder.with(pushedKey: nil) {
+    public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
                                                   DecodingError.Context(codingPath: self.codingPath,
@@ -1403,8 +1604,8 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
-        return try self.decoder.with(pushedKey: nil) {
+    public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                                   DecodingError.Context(codingPath: self.codingPath,
@@ -1427,8 +1628,8 @@
         }
     }
 
-    mutating func superDecoder() throws -> Decoder {
-        return try self.decoder.with(pushedKey: nil) {
+    public mutating func superDecoder() throws -> Decoder {
+        return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(Decoder.self,
                                                   DecodingError.Context(codingPath: self.codingPath,
@@ -1436,12 +1637,6 @@
             }
 
             let value = self.container[self.currentIndex]
-            guard !(value is NSNull) else {
-                throw DecodingError.valueNotFound(Decoder.self,
-                                                  DecodingError.Context(codingPath: self.codingPath,
-                                                                        debugDescription: "Cannot get superDecoder() -- found null value instead."))
-            }
-
             self.currentIndex += 1
             return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
         }
@@ -1451,159 +1646,89 @@
 extension _JSONDecoder : SingleValueDecodingContainer {
     // MARK: SingleValueDecodingContainer Methods
 
-    func decodeNil() -> Bool {
+    private func expectNonNull<T>(_ type: T.Type) throws {
+        guard !self.decodeNil() else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
+        }
+    }
+
+    public func decodeNil() -> Bool {
         return self.storage.topContainer is NSNull
     }
 
-    // These all unwrap the result, since we couldn't have gotten a single value container if the topContainer was null.
-    func decode(_ type: Bool.Type) throws -> Bool {
-        guard let value = try self.unbox(self.storage.topContainer, as: Bool.self) else {
-            throw DecodingError.valueNotFound(Bool.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Bool but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Bool.Type) throws -> Bool {
+        try expectNonNull(Bool.self)
+        return try self.unbox(self.storage.topContainer, as: Bool.self)!
     }
 
-    func decode(_ type: Int.Type) throws -> Int {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int.self) else {
-            throw DecodingError.valueNotFound(Int.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int.Type) throws -> Int {
+        try expectNonNull(Int.self)
+        return try self.unbox(self.storage.topContainer, as: Int.self)!
     }
 
-    func decode(_ type: Int8.Type) throws -> Int8 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int8.self) else {
-            throw DecodingError.valueNotFound(Int8.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int8 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int8.Type) throws -> Int8 {
+        try expectNonNull(Int8.self)
+        return try self.unbox(self.storage.topContainer, as: Int8.self)!
     }
 
-    func decode(_ type: Int16.Type) throws -> Int16 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int16.self) else {
-            throw DecodingError.valueNotFound(Int16.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int16 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int16.Type) throws -> Int16 {
+        try expectNonNull(Int16.self)
+        return try self.unbox(self.storage.topContainer, as: Int16.self)!
     }
 
-    func decode(_ type: Int32.Type) throws -> Int32 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int32.self) else {
-            throw DecodingError.valueNotFound(Int32.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int32 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int32.Type) throws -> Int32 {
+        try expectNonNull(Int32.self)
+        return try self.unbox(self.storage.topContainer, as: Int32.self)!
     }
 
-    func decode(_ type: Int64.Type) throws -> Int64 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int64.self) else {
-            throw DecodingError.valueNotFound(Int64.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int64 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int64.Type) throws -> Int64 {
+        try expectNonNull(Int64.self)
+        return try self.unbox(self.storage.topContainer, as: Int64.self)!
     }
 
-    func decode(_ type: UInt.Type) throws -> UInt {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt.self) else {
-            throw DecodingError.valueNotFound(UInt.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt.Type) throws -> UInt {
+        try expectNonNull(UInt.self)
+        return try self.unbox(self.storage.topContainer, as: UInt.self)!
     }
 
-    func decode(_ type: UInt8.Type) throws -> UInt8 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt8.self) else {
-            throw DecodingError.valueNotFound(UInt8.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt8 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt8.Type) throws -> UInt8 {
+        try expectNonNull(UInt8.self)
+        return try self.unbox(self.storage.topContainer, as: UInt8.self)!
     }
 
-    func decode(_ type: UInt16.Type) throws -> UInt16 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt16.self) else {
-            throw DecodingError.valueNotFound(UInt16.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt16 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt16.Type) throws -> UInt16 {
+        try expectNonNull(UInt16.self)
+        return try self.unbox(self.storage.topContainer, as: UInt16.self)!
     }
 
-    func decode(_ type: UInt32.Type) throws -> UInt32 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt32.self) else {
-            throw DecodingError.valueNotFound(UInt32.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt32 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt32.Type) throws -> UInt32 {
+        try expectNonNull(UInt32.self)
+        return try self.unbox(self.storage.topContainer, as: UInt32.self)!
     }
 
-    func decode(_ type: UInt64.Type) throws -> UInt64 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt64.self) else {
-            throw DecodingError.valueNotFound(UInt64.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt64 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt64.Type) throws -> UInt64 {
+        try expectNonNull(UInt64.self)
+        return try self.unbox(self.storage.topContainer, as: UInt64.self)!
     }
 
-    func decode(_ type: Float.Type) throws -> Float {
-        guard let value = try self.unbox(self.storage.topContainer, as: Float.self) else {
-            throw DecodingError.valueNotFound(Float.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Float but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Float.Type) throws -> Float {
+        try expectNonNull(Float.self)
+        return try self.unbox(self.storage.topContainer, as: Float.self)!
     }
 
-    func decode(_ type: Double.Type) throws -> Double {
-        guard let value = try self.unbox(self.storage.topContainer, as: Double.self) else {
-            throw DecodingError.valueNotFound(Double.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Double but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Double.Type) throws -> Double {
+        try expectNonNull(Double.self)
+        return try self.unbox(self.storage.topContainer, as: Double.self)!
     }
 
-    func decode(_ type: String.Type) throws -> String {
-        guard let value = try self.unbox(self.storage.topContainer, as: String.self) else {
-            throw DecodingError.valueNotFound(String.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected String but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: String.Type) throws -> String {
+        try expectNonNull(String.self)
+        return try self.unbox(self.storage.topContainer, as: String.self)!
     }
 
-    func decode<T : Decodable>(_ type: T.Type) throws -> T {
-        guard let value = try self.unbox(self.storage.topContainer, as: T.self) else {
-            throw DecodingError.valueNotFound(T.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected \(T.self) but found null value instead."))
-        }
-
-        return value
+    public func decode<T : Decodable>(_ type: T.Type) throws -> T {
+        try expectNonNull(T.self)
+        return try self.unbox(self.storage.topContainer, as: T.self)!
     }
 }
 
@@ -1611,8 +1736,7 @@
 
 extension _JSONDecoder {
     /// Returns the given value unboxed from a container.
-    fileprivate func unbox(_ value: Any?, as type: Bool.Type) throws -> Bool? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1620,20 +1744,14 @@
         }
 
         // TODO: Add a flag to coerce non-boolean numbers into Bools?
-        guard number._objCType == .Bool else {
+        guard number._cfTypeID == CFBooleanGetTypeID() else {
             throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
         }
 
-        let bool = number.boolValue
-        guard NSNumber(value: bool) == number else {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
-        }
-
-        return bool
+        return number.boolValue
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int.Type) throws -> Int? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1648,8 +1766,7 @@
         return int
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int8.Type) throws -> Int8? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1664,8 +1781,7 @@
         return int8
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int16.Type) throws -> Int16? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1680,8 +1796,7 @@
         return int16
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int32.Type) throws -> Int32? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1696,8 +1811,7 @@
         return int32
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int64.Type) throws -> Int64? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1712,8 +1826,7 @@
         return int64
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt.Type) throws -> UInt? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1728,8 +1841,7 @@
         return uint
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt8.Type) throws -> UInt8? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1744,8 +1856,7 @@
         return uint8
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt16.Type) throws -> UInt16? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1760,8 +1871,7 @@
         return uint16
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt32.Type) throws -> UInt32? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1776,8 +1886,7 @@
         return uint32
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt64.Type) throws -> UInt64? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1792,8 +1901,7 @@
         return uint64
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Float.Type) throws -> Float? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
         guard !(value is NSNull) else { return nil }
 
         if let number = value as? NSNumber {
@@ -1810,20 +1918,20 @@
 
             return Float(double)
 
-            /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
-             } else if let double = value as? Double {
-             if abs(double) <= Double(Float.max) {
-             return Float(double)
-             }
+        /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
+        } else if let double = value as? Double {
+            if abs(double) <= Double(Float.max) {
+                return Float(double)
+            }
 
-             overflow = true
-             } else if let int = value as? Int {
-             if let float = Float(exactly: int) {
-             return float
-             }
+            overflow = true
+        } else if let int = value as? Int {
+            if let float = Float(exactly: int) {
+                return float
+            }
 
-             overflow = true
-             */
+            overflow = true
+        */
 
         } else if let string = value as? String,
             case .convertFromString(let posInfString, let negInfString, let nanString) = self.options.nonConformingFloatDecodingStrategy {
@@ -1839,8 +1947,7 @@
         throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
     }
 
-    func unbox(_ value: Any?, as type: Double.Type) throws -> Double? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
         guard !(value is NSNull) else { return nil }
 
         if let number = value as? NSNumber {
@@ -1850,16 +1957,16 @@
             // * If it was Decimal, you will get back the nearest approximation
             return number.doubleValue
 
-            /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
-             } else if let double = value as? Double {
-             return double
-             } else if let int = value as? Int {
-             if let double = Double(exactly: int) {
-             return double
-             }
+        /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
+        } else if let double = value as? Double {
+            return double
+        } else if let int = value as? Int {
+            if let double = Double(exactly: int) {
+                return double
+            }
 
-             overflow = true
-             */
+            overflow = true
+        */
 
         } else if let string = value as? String,
             case .convertFromString(let posInfString, let negInfString, let nanString) = self.options.nonConformingFloatDecodingStrategy {
@@ -1875,8 +1982,7 @@
         throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
     }
 
-    func unbox(_ value: Any?, as type: String.Type) throws -> String? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: String.Type) throws -> String? {
         guard !(value is NSNull) else { return nil }
 
         guard let string = value as? String else {
@@ -1886,8 +1992,7 @@
         return string
     }
 
-    func unbox(_ value: Any?, as type: Date.Type) throws -> Date? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
         guard !(value is NSNull) else { return nil }
 
         switch self.options.dateDecodingStrategy {
@@ -1933,8 +2038,7 @@
         }
     }
 
-    func unbox(_ value: Any?, as type: Data.Type) throws -> Data? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
         guard !(value is NSNull) else { return nil }
 
         switch self.options.dataDecodingStrategy {
@@ -1957,15 +2061,23 @@
         }
     }
 
-    func unbox<T : Decodable>(_ value: Any?, as type: T.Type) throws -> T? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Decimal.Type) throws -> Decimal? {
         guard !(value is NSNull) else { return nil }
 
+        // On Darwin we get (value as? Decimal) since JSONSerialization can produce NSDecimalNumber values.
+        // FIXME: Attempt to grab a Decimal value if JSONSerialization on Linux produces one.
+        let doubleValue = try self.unbox(value, as: Double.self)!
+        return Decimal(doubleValue)
+    }
+
+    fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
         let decoded: T
         if T.self == Date.self {
-            decoded = (try self.unbox(value, as: Date.self) as! T)
+            guard let date = try self.unbox(value, as: Date.self) else { return nil }
+            decoded = date as! T
         } else if T.self == Data.self {
-            decoded = (try self.unbox(value, as: Data.self) as! T)
+            guard let data = try self.unbox(value, as: Data.self) else { return nil }
+            decoded = data as! T
         } else if T.self == URL.self {
             guard let urlString = try self.unbox(value, as: String.self) else {
                 return nil
@@ -1975,24 +2087,45 @@
                 throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
                                                                         debugDescription: "Invalid URL string."))
             }
-            
+
             decoded = (url as! T)
+        } else if T.self == Decimal.self {
+            guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
+            decoded = decimal as! T
         } else {
             self.storage.push(container: value)
             decoded = try T(from: self)
             self.storage.popContainer()
         }
-        
+
         return decoded
     }
 }
 
 //===----------------------------------------------------------------------===//
-// Shared Super Key
+// Shared Key Types
 //===----------------------------------------------------------------------===//
 
-fileprivate enum _JSONSuperKey : String, CodingKey {
-    case `super`
+fileprivate struct _JSONKey : CodingKey {
+    public var stringValue: String
+    public var intValue: Int?
+
+    public init?(stringValue: String) {
+        self.stringValue = stringValue
+        self.intValue = nil
+    }
+
+    public init?(intValue: Int) {
+        self.stringValue = "\(intValue)"
+        self.intValue = intValue
+    }
+
+    fileprivate init(index: Int) {
+        self.stringValue = "Index \(index)"
+        self.intValue = index
+    }
+
+    fileprivate static let `super` = _JSONKey(stringValue: "super")!
 }
 
 //===----------------------------------------------------------------------===//
@@ -2018,7 +2151,7 @@
     /// - parameter value: The value that was invalid to encode.
     /// - parameter path: The path of `CodingKey`s taken to encode this value.
     /// - returns: An `EncodingError` with the appropriate path and debug description.
-    fileprivate static func _invalidFloatingPointValue<T : FloatingPoint>(_ value: T, at codingPath: [CodingKey?]) -> EncodingError {
+    fileprivate static func _invalidFloatingPointValue<T : FloatingPoint>(_ value: T, at codingPath: [CodingKey]) -> EncodingError {
         let valueDescription: String
         if value == T.infinity {
             valueDescription = "\(T.self).infinity"
@@ -2027,7 +2160,7 @@
         } else {
             valueDescription = "\(T.self).nan"
         }
-        
+
         let debugDescription = "Unable to encode \(valueDescription) directly in JSON. Use JSONEncoder.NonConformingFloatEncodingStrategy.convertToString to specify how the value should be encoded."
         return .invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: debugDescription))
     }
diff --git a/Foundation/Locale.swift b/Foundation/Locale.swift
index 7b81c63..1544767 100644
--- a/Foundation/Locale.swift
+++ b/Foundation/Locale.swift
@@ -466,3 +466,20 @@
         return result!
     }
 }
+
+extension Locale : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case identifier
+    }
+    
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        let identifier = try container.decode(String.self, forKey: .identifier)
+        self.init(identifier: identifier)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(self.identifier, forKey: .identifier)
+    }
+}
diff --git a/Foundation/NSAffineTransform.swift b/Foundation/NSAffineTransform.swift
index 0b3fc61..cfd0504 100644
--- a/Foundation/NSAffineTransform.swift
+++ b/Foundation/NSAffineTransform.swift
@@ -455,3 +455,25 @@
         return AffineTransform._unconditionallyBridgeFromObjectiveC(self)
     }
 }
+
+extension AffineTransform : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        m11 = try container.decode(CGFloat.self)
+        m12 = try container.decode(CGFloat.self)
+        m21 = try container.decode(CGFloat.self)
+        m22 = try container.decode(CGFloat.self)
+        tX  = try container.decode(CGFloat.self)
+        tY  = try container.decode(CGFloat.self)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(self.m11)
+        try container.encode(self.m12)
+        try container.encode(self.m21)
+        try container.encode(self.m22)
+        try container.encode(self.tX)
+        try container.encode(self.tY)
+    }
+}
diff --git a/Foundation/NSCFBoolean.swift b/Foundation/NSCFBoolean.swift
index 90e223b..23577ff 100644
--- a/Foundation/NSCFBoolean.swift
+++ b/Foundation/NSCFBoolean.swift
@@ -78,7 +78,10 @@
     override var objCType: UnsafePointer<Int8> {
         // This must never be fixed to be "B", although that would
         // cause correct old-style archiving when this is unarchived.
-        return UnsafePointer<Int8>(bitPattern: UInt(_NSSimpleObjCType.Char.rawValue.value))!
+        func _objCType(_ staticString: StaticString) -> UnsafePointer<Int8> {
+            return UnsafeRawPointer(staticString.utf8Start).assumingMemoryBound(to: Int8.self)
+        }
+        return _objCType("c")
     }
     
     internal override func _cfNumberType() -> CFNumberType  {
diff --git a/Foundation/NSCFString.swift b/Foundation/NSCFString.swift
index 6d0d8a1..1eb29b1 100644
--- a/Foundation/NSCFString.swift
+++ b/Foundation/NSCFString.swift
@@ -59,13 +59,21 @@
 
 internal final class _NSCFConstantString : _NSCFString {
     internal var _ptr : UnsafePointer<UInt8> {
-        let offset = MemoryLayout<OpaquePointer>.size + MemoryLayout<Int32>.size + MemoryLayout<Int32>.size + MemoryLayout<_CFInfo>.size
+        // FIXME: Split expression as a work-around for slow type
+        //        checking (tracked by SR-5322).
+        let offTemp1 = MemoryLayout<OpaquePointer>.size + MemoryLayout<Int32>.size
+        let offTemp2 = MemoryLayout<Int32>.size + MemoryLayout<_CFInfo>.size
+        let offset = offTemp1 + offTemp2
         let ptr = Unmanaged.passUnretained(self).toOpaque()
         return ptr.load(fromByteOffset: offset, as: UnsafePointer<UInt8>.self)
     }
 
     private var _lenOffset : Int {
-        return MemoryLayout<OpaquePointer>.size + MemoryLayout<Int32>.size + MemoryLayout<Int32>.size + MemoryLayout<_CFInfo>.size + MemoryLayout<UnsafePointer<UInt8>>.size
+        // FIXME: Split expression as a work-around for slow type
+        //        checking (tracked by SR-5322).
+        let offTemp1 = MemoryLayout<OpaquePointer>.size + MemoryLayout<Int32>.size
+        let offTemp2 = MemoryLayout<Int32>.size + MemoryLayout<_CFInfo>.size
+        return offTemp1 + offTemp2 + MemoryLayout<UnsafePointer<UInt8>>.size
     }
 
     private var _lenPtr :  UnsafeMutableRawPointer {
diff --git a/Foundation/NSCharacterSet.swift b/Foundation/NSCharacterSet.swift
index c2c72b7..ce490af 100644
--- a/Foundation/NSCharacterSet.swift
+++ b/Foundation/NSCharacterSet.swift
@@ -50,13 +50,18 @@
     }
     
     open override func isEqual(_ value: Any?) -> Bool {
+        guard let runtimeClass = _CFRuntimeGetClassWithTypeID(CFCharacterSetGetTypeID()) else {
+            fatalError("Could not obtain CFRuntimeClass of CFCharacterSet")
+        }
+
+        guard let equalFunction = runtimeClass.pointee.equal else {
+            fatalError("Could not obtain equal function from CFRuntimeClass of CFCharacterSet")
+        }
+
         switch value {
-        case let other as CharacterSet:
-            return CFEqual(_cfObject, other._cfObject)
-        case let other as NSCharacterSet:
-            return CFEqual(_cfObject, other._cfObject)
-        default:
-            return false
+        case let other as CharacterSet: return equalFunction(self._cfObject, other._cfObject) == true
+        case let other as NSCharacterSet: return equalFunction(self._cfObject, other._cfObject) == true
+        default: return false
         }
     }
     
diff --git a/Foundation/NSDecimal.swift b/Foundation/NSDecimal.swift
index e22cfcd..0eac26a 100644
--- a/Foundation/NSDecimal.swift
+++ b/Foundation/NSDecimal.swift
@@ -24,7 +24,7 @@
             return Int32(__exponent)
         }
         set {
-            __exponent = Int8(extendingOrTruncating: newValue)
+            __exponent = Int8(truncatingIfNeeded: newValue)
         }
     }
     // length == 0 && isNegative -> NaN
@@ -90,7 +90,7 @@
 
     public init(_exponent: Int32, _length: UInt32, _isNegative: UInt32, _isCompact: UInt32, _reserved: UInt32, _mantissa: (UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16)){
         self._mantissa = _mantissa
-        self.__exponent = Int8(extendingOrTruncating: _exponent)
+        self.__exponent = Int8(truncatingIfNeeded: _exponent)
         self.__lengthAndFlags = UInt8(_length & 0b1111)
         self.__reserved = 0
         self._isNegative = _isNegative
@@ -412,21 +412,21 @@
             while mantissa != 0 && i < NSDecimalMaxSize {
                 switch i {
                 case 0:
-                    _mantissa.0 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.0 = UInt16(truncatingIfNeeded:mantissa)
                 case 1:
-                    _mantissa.1 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.1 = UInt16(truncatingIfNeeded:mantissa)
                 case 2:
-                    _mantissa.2 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.2 = UInt16(truncatingIfNeeded:mantissa)
                 case 3:
-                    _mantissa.3 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.3 = UInt16(truncatingIfNeeded:mantissa)
                 case 4:
-                    _mantissa.4 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.4 = UInt16(truncatingIfNeeded:mantissa)
                 case 5:
-                    _mantissa.5 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.5 = UInt16(truncatingIfNeeded:mantissa)
                 case 6:
-                    _mantissa.6 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.6 = UInt16(truncatingIfNeeded:mantissa)
                 case 7:
-                    _mantissa.7 = UInt16(extendingOrTruncating:mantissa)
+                    _mantissa.7 = UInt16(truncatingIfNeeded:mantissa)
                 default:
                     fatalError("initialization overflow")
                 }
@@ -592,13 +592,13 @@
     for i in 0..<d._length {
         let accumulator: UInt32 = UInt32(d[i]) * UInt32(mul) + carry
         carry = accumulator >> 16
-        d[i] = UInt16(extendingOrTruncating: accumulator)
+        d[i] = UInt16(truncatingIfNeeded: accumulator)
     }
     if carry != 0 {
         if d._length >= Decimal.maxSize {
             return .overflow
         }
-        d[d._length] = UInt16(extendingOrTruncating: carry)
+        d[d._length] = UInt16(truncatingIfNeeded: carry)
         d._length += 1
     }
     return .noError
@@ -609,13 +609,13 @@
     for i in 0..<d._length {
         let accumulator: UInt32 = UInt32(d[i]) + carry
         carry = accumulator >> 16
-        d[i] = UInt16(extendingOrTruncating: accumulator)
+        d[i] = UInt16(truncatingIfNeeded: accumulator)
     }
     if carry != 0 {
         if d._length >= Decimal.maxSize {
             return .overflow
         }
-        d[d._length] = UInt16(extendingOrTruncating: carry)
+        d[d._length] = UInt16(truncatingIfNeeded: carry)
         d._length += 1
     }
     return .noError
@@ -763,8 +763,8 @@
             if i + j < big._length {
                 let bigij = UInt32(big[i+j])
                 accumulator = UInt32(carry) + bigij + UInt32(right[j]) * UInt32(left[i])
-                carry = UInt16(extendingOrTruncating:accumulator >> 16)
-                big[i+j] = UInt16(extendingOrTruncating:accumulator)
+                carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+                big[i+j] = UInt16(truncatingIfNeeded:accumulator)
             } else if carry != 0 || (right[j] == 0 && left[j] == 0) {
                 return .overflow
             }
@@ -904,7 +904,7 @@
             acc = acc & 0xffff;
             acc = 0xffff + UInt32(u[ul - vl + i - UInt32(j) - UInt32(1)]) - acc + sk; // subtract
             sk = acc >> 16;
-            u[ul - vl + i - UInt32(j) - UInt32(1)] = UInt16(extendingOrTruncating:acc)
+            u[ul - vl + i - UInt32(j) - UInt32(1)] = UInt16(truncatingIfNeeded:acc)
         }
 
         // D5: test remainder
@@ -920,7 +920,7 @@
                 let vl = v._length
                 acc = UInt32(v[i]) + UInt32(u[UInt32(ul) - UInt32(vl) + UInt32(i) - UInt32(j) - UInt32(1)]) + k
                 k = acc >> 16;
-                u[UInt32(ul) - UInt32(vl) + UInt32(i) - UInt32(j) - UInt32(1)] = UInt16(extendingOrTruncating:acc)
+                u[UInt32(ul) - UInt32(vl) + UInt32(i) - UInt32(j) - UInt32(1)] = UInt16(truncatingIfNeeded:acc)
             }
             // k must be == 1 here
         }
@@ -1173,8 +1173,8 @@
         let li = UInt32(left[i])
         let ri = UInt32(right[i])
         accumulator = li + ri + UInt32(carry)
-        carry = UInt16(extendingOrTruncating:accumulator >> 16)
-        result[i] = UInt16(extendingOrTruncating:accumulator)
+        carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+        result[i] = UInt16(truncatingIfNeeded:accumulator)
         i += 1
     }
 
@@ -1182,8 +1182,8 @@
         if carry != 0 {
             let li = UInt32(left[i])
             accumulator = li + UInt32(carry)
-            carry = UInt16(extendingOrTruncating:accumulator >> 16)
-            result[i] = UInt16(extendingOrTruncating:accumulator)
+            carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+            result[i] = UInt16(truncatingIfNeeded:accumulator)
             i += 1
         } else {
             while i < left._length {
@@ -1197,8 +1197,8 @@
         if carry != 0 {
             let ri = UInt32(right[i])
             accumulator = ri + UInt32(carry)
-            carry = UInt16(extendingOrTruncating:accumulator >> 16)
-            result[i] = UInt16(extendingOrTruncating:accumulator)
+            carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+            result[i] = UInt16(truncatingIfNeeded:accumulator)
             i += 1
         } else {
             while i < right._length {
@@ -1240,8 +1240,8 @@
         let li = UInt32(left[i])
         let ri = UInt32(right[i])
         accumulator = 0xffff + li - ri + UInt32(carry)
-        carry = UInt16(extendingOrTruncating:accumulator >> 16)
-        result[i] = UInt16(extendingOrTruncating:accumulator)
+        carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+        result[i] = UInt16(truncatingIfNeeded:accumulator)
         i += 1
     }
 
@@ -1249,8 +1249,8 @@
         if carry != 0 {
             let li = UInt32(left[i])
             accumulator = 0xffff + li // + no carry
-            carry = UInt16(extendingOrTruncating:accumulator >> 16)
-            result[i] = UInt16(extendingOrTruncating:accumulator)
+            carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+            result[i] = UInt16(truncatingIfNeeded:accumulator)
             i += 1
         } else {
             while i < left._length {
@@ -1263,8 +1263,8 @@
     while i < right._length {
         let ri = UInt32(right[i])
         accumulator = 0xffff - ri + UInt32(carry)
-        carry = UInt16(extendingOrTruncating:accumulator >> 16)
-        result[i] = UInt16(extendingOrTruncating:accumulator)
+        carry = UInt16(truncatingIfNeeded:accumulator >> 16)
+        result[i] = UInt16(truncatingIfNeeded:accumulator)
         i += 1
     }
 
@@ -2087,3 +2087,58 @@
         return result
     }
 }
+
+extension Decimal : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case exponent
+        case length
+        case isNegative
+        case isCompact
+        case mantissa
+    }
+    
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        let exponent = try container.decode(CInt.self, forKey: .exponent)
+        let length = try container.decode(CUnsignedInt.self, forKey: .length)
+        let isNegative = try container.decode(Bool.self, forKey: .isNegative)
+        let isCompact = try container.decode(Bool.self, forKey: .isCompact)
+        
+        var mantissaContainer = try container.nestedUnkeyedContainer(forKey: .mantissa)
+        var mantissa: (CUnsignedShort, CUnsignedShort, CUnsignedShort, CUnsignedShort,
+            CUnsignedShort, CUnsignedShort, CUnsignedShort, CUnsignedShort) = (0,0,0,0,0,0,0,0)
+        mantissa.0 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.1 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.2 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.3 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.4 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.5 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.6 = try mantissaContainer.decode(CUnsignedShort.self)
+        mantissa.7 = try mantissaContainer.decode(CUnsignedShort.self)
+        
+        self.init(_exponent: exponent,
+                  _length: length,
+                  _isNegative: CUnsignedInt(isNegative ? 1 : 0),
+                  _isCompact: CUnsignedInt(isCompact ? 1 : 0),
+                  _reserved: 0,
+                  _mantissa: mantissa)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(_exponent, forKey: .exponent)
+        try container.encode(_length, forKey: .length)
+        try container.encode(_isNegative == 0 ? false : true, forKey: .isNegative)
+        try container.encode(_isCompact == 0 ? false : true, forKey: .isCompact)
+        
+        var mantissaContainer = container.nestedUnkeyedContainer(forKey: .mantissa)
+        try mantissaContainer.encode(_mantissa.0)
+        try mantissaContainer.encode(_mantissa.1)
+        try mantissaContainer.encode(_mantissa.2)
+        try mantissaContainer.encode(_mantissa.3)
+        try mantissaContainer.encode(_mantissa.4)
+        try mantissaContainer.encode(_mantissa.5)
+        try mantissaContainer.encode(_mantissa.6)
+        try mantissaContainer.encode(_mantissa.7)
+    }
+}
diff --git a/Foundation/NSDecimalNumber.swift b/Foundation/NSDecimalNumber.swift
index 1e049d6..06d4aa4 100644
--- a/Foundation/NSDecimalNumber.swift
+++ b/Foundation/NSDecimalNumber.swift
@@ -408,7 +408,7 @@
         }
     }
     
-    open class func `default`() -> NSDecimalNumberHandler {
+    open class var `default`: NSDecimalNumberHandler {
         return defaultBehavior
     }
     // rounding mode: NSRoundPlain
diff --git a/Foundation/NSError.swift b/Foundation/NSError.swift
index 14d05cc..abec7fa 100644
--- a/Foundation/NSError.swift
+++ b/Foundation/NSError.swift
@@ -274,6 +274,37 @@
     var errorUserInfo: [String : Any] { get }
 }
 
+public extension CustomNSError {
+    /// Default domain of the error.
+    static var errorDomain: String {
+        return String(reflecting: self)
+    }
+
+    /// The error code within the given domain.
+    var errorCode: Int {
+        return _swift_getDefaultErrorCode(self)
+    }
+
+    /// The default user-info dictionary.
+    var errorUserInfo: [String : Any] {
+        return [:]
+    }
+}
+
+extension CustomNSError where Self: RawRepresentable, Self.RawValue: SignedInteger {
+    // The error code of Error with integral raw values is the raw value.
+    public var errorCode: Int {
+        return numericCast(self.rawValue)
+    }
+}
+
+extension CustomNSError where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
+    // The error code of Error with integral raw values is the raw value.
+    public var errorCode: Int {
+        return numericCast(self.rawValue)
+    }
+}
+
 public extension Error where Self : CustomNSError {
     /// Default implementation for customized NSErrors.
     var _domain: String { return Self.errorDomain }
@@ -282,6 +313,16 @@
     var _code: Int { return self.errorCode }
 }
 
+public extension Error where Self: CustomNSError, Self: RawRepresentable, Self.RawValue: SignedInteger {
+    /// Default implementation for customized NSErrors.
+    var _code: Int { return self.errorCode }
+}
+
+public extension Error where Self: CustomNSError, Self: RawRepresentable, Self.RawValue: UnsignedInteger {
+    /// Default implementation for customized NSErrors.
+    var _code: Int { return self.errorCode }
+}
+
 public extension Error {
     /// Retrieve the localized description for this error.
     var localizedDescription: String {
diff --git a/Foundation/NSGeometry.swift b/Foundation/NSGeometry.swift
index 454014a..80c8d25 100644
--- a/Foundation/NSGeometry.swift
+++ b/Foundation/NSGeometry.swift
@@ -25,6 +25,20 @@
     }
 }
 
+extension CGPoint {
+    public static var zero: CGPoint {
+        return CGPoint(x: CGFloat(0), y: CGFloat(0))
+    }
+    
+    public init(x: Int, y: Int) {
+        self.init(x: CGFloat(x), y: CGFloat(y))
+    }
+    
+    public init(x: Double, y: Double) {
+        self.init(x: CGFloat(x), y: CGFloat(y))
+    }
+}
+
 extension CGPoint: Equatable {
     public static func ==(lhs: CGPoint, rhs: CGPoint) -> Bool {
         return lhs.x == rhs.x && lhs.y == rhs.y
@@ -76,6 +90,21 @@
     }
 }
 
+extension CGPoint : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let x = try container.decode(CGFloat.self)
+        let y = try container.decode(CGFloat.self)
+        self.init(x: x, y: y)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(x)
+        try container.encode(y)
+    }
+}
+
 public struct CGSize {
     public var width: CGFloat
     public var height: CGFloat
@@ -88,6 +117,20 @@
     }
 }
 
+extension CGSize {
+    public static var zero: CGSize {
+        return CGSize(width: CGFloat(0), height: CGFloat(0))
+    }
+    
+    public init(width: Int, height: Int) {
+        self.init(width: CGFloat(width), height: CGFloat(height))
+    }
+    
+    public init(width: Double, height: Double) {
+        self.init(width: CGFloat(width), height: CGFloat(height))
+    }
+}
+
 extension CGSize: Equatable {
     public static func ==(lhs: CGSize, rhs: CGSize) -> Bool {
         return lhs.width == rhs.width && lhs.height == rhs.height
@@ -139,6 +182,21 @@
     }
 }
 
+extension CGSize : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let width = try container.decode(CGFloat.self)
+        let height = try container.decode(CGFloat.self)
+        self.init(width: width, height: height)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(width)
+        try container.encode(height)
+    }
+}
+
 public struct CGRect {
     public var origin: CGPoint
     public var size: CGSize
@@ -151,12 +209,57 @@
     }
 }
 
+extension CGRect {
+    public static var zero: CGRect {
+        return CGRect(origin: CGPoint(), size: CGSize())
+    }
+    
+    public init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {
+        self.init(origin: CGPoint(x: x, y: y), size: CGSize(width: width, height: height))
+    }
+    
+    public init(x: Double, y: Double, width: Double, height: Double) {
+        self.init(origin: CGPoint(x: x, y: y), size: CGSize(width: width, height: height))
+    }
+    
+    public init(x: Int, y: Int, width: Int, height: Int) {
+        self.init(origin: CGPoint(x: x, y: y), size: CGSize(width: width, height: height))
+    }
+}
+
+extension CGRect {
+    public static let null = CGRect(x: CGFloat.infinity,
+                                    y: CGFloat.infinity,
+                                    width: CGFloat(0),
+                                    height: CGFloat(0))
+    
+    public static let infinite = CGRect(x: -CGFloat.greatestFiniteMagnitude / 2,
+                                        y: -CGFloat.greatestFiniteMagnitude / 2,
+                                        width: CGFloat.greatestFiniteMagnitude,
+                                        height: CGFloat.greatestFiniteMagnitude)
+}
+
 extension CGRect: Equatable {
     public static func ==(lhs: CGRect, rhs: CGRect) -> Bool {
         return lhs.origin == rhs.origin && lhs.size == rhs.size
     }
 }
 
+extension CGRect : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let origin = try container.decode(CGPoint.self)
+        let size = try container.decode(CGSize.self)
+        self.init(origin: origin, size: size)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(origin)
+        try container.encode(size)
+    }
+}
+
 public typealias NSPoint = CGPoint
 
 public typealias NSPointPointer = UnsafeMutablePointer<NSPoint>
diff --git a/Foundation/NSJSONSerialization.swift b/Foundation/NSJSONSerialization.swift
index ebc7bea..13e639e 100644
--- a/Foundation/NSJSONSerialization.swift
+++ b/Foundation/NSJSONSerialization.swift
@@ -31,6 +31,7 @@
         public init(rawValue: UInt) { self.rawValue = rawValue }
         
         public static let prettyPrinted = WritingOptions(rawValue: 1 << 0)
+        public static let sortedKeys = WritingOptions(rawValue: 1 << 1)
     }
 }
 
@@ -116,6 +117,7 @@
         
         var writer = JSONWriter(
             pretty: opt.contains(.prettyPrinted),
+            sortedKeys: opt.contains(.sortedKeys),
             writer: { (str: String?) in
                 if let str = str {
                     jsonStr.append(str)
@@ -289,6 +291,7 @@
     private let maxIntLength = String(describing: Int.max).characters.count
     var indent = 0
     let pretty: Bool
+    let sortedKeys: Bool
     let writer: (String?) -> Void
     
     private lazy var _numberformatter: CFNumberFormatter = {
@@ -299,8 +302,9 @@
         return formatter
     }()
 
-    init(pretty: Bool = false, writer: @escaping (String?) -> Void) {
+    init(pretty: Bool = false, sortedKeys: Bool = false, writer: @escaping (String?) -> Void) {
         self.pretty = pretty
+        self.sortedKeys = sortedKeys
         self.writer = writer
     }
     
@@ -459,8 +463,8 @@
             throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Number cannot be infinity or NaN"])
         }
         
-        switch num._objCType {
-        case .Bool:
+        switch num._cfTypeID {
+        case CFBooleanGetTypeID():
             serializeBool(num.boolValue)
         default:
             writer(_serializationString(for: num))
@@ -499,10 +503,10 @@
             writer("\n")
             incAndWriteIndent()
         }
-        
+
         var first = true
-        
-        for (key, value) in dict {
+
+        func serializeDictionaryElement(key: AnyHashable, value: Any) throws {
             if first {
                 first = false
             } else if pretty {
@@ -511,15 +515,37 @@
             } else {
                 writer(",")
             }
-            
-            if key is String {
-                try serializeString(key as! String)
+
+            if let key = key as? String {
+                try serializeString(key)
             } else {
                 throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
             }
             pretty ? writer(": ") : writer(":")
             try serializeJSON(value)
         }
+
+        if sortedKeys {
+            let elems = try dict.sorted(by: { a, b in
+                guard let a = a.key as? String,
+                    let b = b.key as? String else {
+                        throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
+                }
+                let options: NSString.CompareOptions = [.numeric, .caseInsensitive, .forcedOrdering]
+                let range: Range<String.Index>  = a.startIndex..<a.endIndex
+                let locale = NSLocale.system
+
+                return a.compare(b, options: options, range: range, locale: locale) == .orderedAscending
+            })
+            for elem in elems {
+                try serializeDictionaryElement(key: elem.key, value: elem.value)
+            }
+        } else {
+            for (key, value) in dict {
+                try serializeDictionaryElement(key: key, value: value)
+            }
+        }
+
         if pretty {
             writer("\n")
             decAndWriteIndent()
diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift
index 47fc2f8..b977cc8 100644
--- a/Foundation/NSKeyedUnarchiver.swift
+++ b/Foundation/NSKeyedUnarchiver.swift
@@ -683,10 +683,10 @@
     }
     
     open override func decodeBool(forKey key: String) -> Bool {
-        guard let result : NSNumber = _decodeValue(forKey: key) else {
+        guard let result : Bool = _decodeValue(forKey: key) else {
             return false
         }
-        return result.boolValue
+        return result
     }
     
     open override func decodeInt32(forKey key: String) -> Int32 {
diff --git a/Foundation/NSLocale.swift b/Foundation/NSLocale.swift
index 266f377..4b1b44f 100644
--- a/Foundation/NSLocale.swift
+++ b/Foundation/NSLocale.swift
@@ -84,7 +84,7 @@
         return CFLocaleCopyCurrent()._swiftObject
     }
     
-    open class func systemLocale() -> Locale {
+    open class var system: Locale {
         return CFLocaleGetSystem()._swiftObject
     }
 }
diff --git a/Foundation/NSNotification.swift b/Foundation/NSNotification.swift
index 223512b..688b86a 100644
--- a/Foundation/NSNotification.swift
+++ b/Foundation/NSNotification.swift
@@ -90,6 +90,7 @@
     fileprivate var name: Notification.Name?
     fileprivate var block: ((Notification) -> Void)?
     fileprivate var sender: AnyObject?
+    fileprivate var queue: OperationQueue?
 }
 
 extension Sequence where Iterator.Element : NSNotificationReceiver {
@@ -159,7 +160,12 @@
                 continue
             }
             
-            block(notification)
+            if let queue = observer.queue, queue != OperationQueue.current {
+                queue.addOperation { block(notification) }
+                queue.waitUntilAllOperationsAreFinished()
+            } else {
+                block(notification)
+            }
         }
     }
 
@@ -183,10 +189,6 @@
     }
     
     open func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, usingBlock block: @escaping (Notification) -> Void) -> NSObjectProtocol {
-        if queue != nil {
-            NSUnimplemented()
-        }
-
         let object = NSObject()
         
         let newObserver = NSNotificationReceiver()
@@ -194,6 +196,7 @@
         newObserver.name = name
         newObserver.block = block
         newObserver.sender = _SwiftValue.store(obj)
+        newObserver.queue = queue
 
         _observersLock.synchronized({
             _observers.append(newObserver)
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index 5cc73a6..1e225ee 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -198,14 +198,17 @@
 
 }
 
+private struct CFSInt128Struct {
+    var high: Int64
+    var low: UInt64
+}
+
 open class NSNumber : NSValue {
     typealias CFType = CFNumber
     // This layout MUST be the same as CFNumber so that they are bridgeable
     private var _base = _CFInfo(typeID: CFNumberGetTypeID())
     private var _pad: UInt64 = 0
 
-    internal let _objCType: _NSSimpleObjCType
-
     internal var _cfObject: CFType {
         return unsafeBitCast(self, to: CFType.self)
     }
@@ -230,93 +233,123 @@
     }
 
     open override var objCType: UnsafePointer<Int8> {
-        return UnsafePointer<Int8>(bitPattern: UInt(_objCType.rawValue.value))!
+        func _objCType(_ staticString: StaticString) -> UnsafePointer<Int8> {
+            return UnsafeRawPointer(staticString.utf8Start).assumingMemoryBound(to: Int8.self)
+        }
+        let numberType = _CFNumberGetType2(_cfObject)
+        switch numberType {
+        case kCFNumberSInt8Type:
+            return _objCType("c")
+        case kCFNumberSInt16Type:
+            return _objCType("s")
+        case kCFNumberSInt32Type:
+            return _objCType("i")
+        case kCFNumberSInt64Type:
+            return _objCType("q")
+        case kCFNumberFloat32Type:
+            return _objCType("f")
+        case kCFNumberFloat64Type:
+            return _objCType("d")
+        case kCFNumberSInt128Type:
+            return _objCType("Q")
+        default:
+            fatalError("unsupported CFNumberType: '\(numberType)'")
+        }
     }
     
     deinit {
         _CFDeinit(self)
     }
     
-    public init(value: Int8) {
-        _objCType = .Char
-        super.init()
-        _CFNumberInitInt8(_cfObject, value)
+    private convenience init(bytes: UnsafeRawPointer, numberType: CFNumberType) {
+        let cfnumber = CFNumberCreate(nil, numberType, bytes)
+        self.init(factory: { unsafeBitCast(cfnumber, to: NSNumber.self) })
     }
     
-    public init(value: UInt8) {
-        _objCType = .UChar
-        super.init()
-        _CFNumberInitUInt8(_cfObject, value)
+    public convenience init(value: Int8) {
+        var value = value
+        self.init(bytes: &value, numberType: kCFNumberSInt8Type)
     }
     
-    public init(value: Int16) {
-        _objCType = .Short
-        super.init()
-        _CFNumberInitInt16(_cfObject, value)
+    public convenience init(value: UInt8) {
+        var value = Int16(value)
+        self.init(bytes: &value, numberType: kCFNumberSInt16Type)
     }
     
-    public init(value: UInt16) {
-        _objCType = .UShort
-        super.init()
-        _CFNumberInitUInt16(_cfObject, value)
+    public convenience init(value: Int16) {
+        var value = value
+        self.init(bytes: &value, numberType: kCFNumberSInt16Type)
     }
     
-    public init(value: Int32) {
-        _objCType = .Long
-        super.init()
-        _CFNumberInitInt32(_cfObject, value)
+    public convenience init(value: UInt16) {
+        var value = Int32(value)
+        self.init(bytes: &value, numberType: kCFNumberSInt32Type)
     }
     
-    public init(value: UInt32) {
-        _objCType = .ULong
-        super.init()
-        _CFNumberInitUInt32(_cfObject, value)
+    public convenience init(value: Int32) {
+        var value = value
+        self.init(bytes: &value, numberType: kCFNumberSInt32Type)
     }
     
-    public init(value: Int) {
-        _objCType = .Int
-        super.init()
-        _CFNumberInitInt(_cfObject, value)
+    public convenience init(value: UInt32) {
+        var value = Int64(value)
+        self.init(bytes: &value, numberType: kCFNumberSInt64Type)
     }
     
-    public init(value: UInt) {
-        _objCType = .UInt
-        super.init()
-        _CFNumberInitUInt(_cfObject, value)
+    public convenience init(value: Int) {
+        var value = value
+        #if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+            self.init(bytes: &value, numberType: kCFNumberSInt64Type)
+        #elseif arch(i386) || arch(arm)
+            self.init(bytes: &value, numberType: kCFNumberSInt32Type)
+        #endif
     }
     
-    public init(value: Int64) {
-        _objCType = .LongLong
-        super.init()
-        _CFNumberInitInt64(_cfObject, value)
+    public convenience init(value: UInt) {
+    #if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+        if value > UInt64(Int64.max) {
+            var value = CFSInt128Struct(high: 0, low: UInt64(value))
+            self.init(bytes: &value, numberType: kCFNumberSInt128Type)
+        } else {
+            var value = Int64(value)
+            self.init(bytes: &value, numberType: kCFNumberSInt64Type)
+        }
+    #elseif arch(i386) || arch(arm)
+        var value = Int64(value)
+        self.init(bytes: &value, numberType: kCFNumberSInt64Type)
+    #endif
     }
     
-    public init(value: UInt64) {
-        _objCType = .ULongLong
-        super.init()
-        _CFNumberInitUInt64(_cfObject, value)
+    public convenience init(value: Int64) {
+        var value = value
+        self.init(bytes: &value, numberType: kCFNumberSInt64Type)
     }
     
-    public init(value: Float) {
-        _objCType = .Float
-        super.init()
-        _CFNumberInitFloat(_cfObject, value)
+    public convenience init(value: UInt64) {
+        if value > UInt64(Int64.max) {
+            var value = CFSInt128Struct(high: 0, low: UInt64(value))
+            self.init(bytes: &value, numberType: kCFNumberSInt128Type)
+        } else {
+            var value = Int64(value)
+            self.init(bytes: &value, numberType: kCFNumberSInt64Type)
+        }
     }
     
-    public init(value: Double) {
-        _objCType = .Double
-        super.init()
-        _CFNumberInitDouble(_cfObject, value)
+    public convenience init(value: Float) {
+        var value = value
+        self.init(bytes: &value, numberType: kCFNumberFloatType)
     }
     
-    public init(value: Bool) {
-        _objCType = .Bool
-        super.init()
-        _CFNumberInitBool(_cfObject, value)
+    public convenience init(value: Double) {
+        var value = value
+        self.init(bytes: &value, numberType: kCFNumberDoubleType)
+    }
+
+    public convenience init(value: Bool) {
+        self.init(factory: value._bridgeToObjectiveC)
     }
 
     override internal init() {
-        _objCType = .Undef
         super.init()
     }
 
@@ -381,83 +414,63 @@
     }
 
     open var int8Value: Int8 {
-        var val: Int8 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Int8>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberCharType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
 
     open var uint8Value: UInt8 {
-        var val: UInt8 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<UInt8>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberCharType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
     
     open var int16Value: Int16 {
-        var val: Int16 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Int16>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberShortType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
     
     open var uint16Value: UInt16 {
-        var val: UInt16 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<UInt16>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberShortType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
     
     open var int32Value: Int32 {
-        var val: Int32 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Int32>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberIntType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
     
     open var uint32Value: UInt32 {
-        var val: UInt32 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<UInt32>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberIntType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
     
     open var int64Value: Int64 {
-        var val: Int64 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Int64>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberLongLongType, value)
-        }
-        return val
+        var value: Int64 = 0
+        CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
+        return .init(truncatingIfNeeded: value)
     }
     
     open var uint64Value: UInt64 {
-        var val: UInt64 = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<UInt64>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberLongLongType, value)
-        }
-        return val
+        var value = CFSInt128Struct(high: 0, low: 0)
+        CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
+        return .init(truncatingIfNeeded: value.low)
     }
     
     open var floatValue: Float {
-        var val: Float = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Float>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberFloatType, value)
-        }
-        return val
+        var value: Float = 0
+        CFNumberGetValue(_cfObject, kCFNumberFloatType, &value)
+        return value
     }
     
     open var doubleValue: Double {
-        var val: Double = 0
-        withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Double>) -> Void in
-            CFNumberGetValue(_cfObject, kCFNumberDoubleType, value)
-        }
-        return val
+        var value: Double = 0
+        CFNumberGetValue(_cfObject, kCFNumberDoubleType, &value)
+        return value
     }
     
     open var boolValue: Bool {
@@ -503,7 +516,24 @@
     }
 
     open func compare(_ otherNumber: NSNumber) -> ComparisonResult {
-        return ._fromCF(CFNumberCompare(_cfObject, otherNumber._cfObject, nil))
+        switch (objCType.pointee, otherNumber.objCType.pointee) {
+        case (0x66, _), (_, 0x66), (0x66, 0x66): fallthrough // 'f' float
+        case (0x64, _), (_, 0x64), (0x64, 0x64):             // 'd' double
+            let (lhs, rhs) = (doubleValue, otherNumber.doubleValue)
+            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 }
+            return .orderedSame
+        }
     }
 
     open func description(withLocale locale: Locale?) -> String {
@@ -612,7 +642,7 @@
             }
         }
     }
-    
+
     open override var classForCoder: AnyClass { return NSNumber.self }
 }
 
diff --git a/Foundation/NSPersonNameComponents.swift b/Foundation/NSPersonNameComponents.swift
index df2ca90..52e5a0d 100644
--- a/Foundation/NSPersonNameComponents.swift
+++ b/Foundation/NSPersonNameComponents.swift
@@ -64,6 +64,28 @@
         }
         return copy
     }
+
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let object = object else { return false }
+
+        switch object {
+        case let other as NSPersonNameComponents: return self.isEqual(other)
+        case let other as PersonNameComponents: return self.isEqual(other._bridgeToObjectiveC())
+        default: return false
+        }
+    }
+
+    private func isEqual(_ other: NSPersonNameComponents) -> Bool {
+        if self === other { return true }
+        
+        return (self.namePrefix == other.namePrefix
+            && self.givenName == other.givenName
+            && self.middleName == other.middleName
+            && self.familyName == other.familyName
+            && self.nameSuffix == other.nameSuffix
+            && self.nickname == other.nickname
+            && self.phoneticRepresentation == other.phoneticRepresentation)
+    }
     
     /* The below examples all assume the full name Dr. Johnathan Maple Appleseed Esq., nickname "Johnny" */
     
diff --git a/Foundation/NSRange.swift b/Foundation/NSRange.swift
index 699ebb1..91a8aba 100644
--- a/Foundation/NSRange.swift
+++ b/Foundation/NSRange.swift
@@ -126,7 +126,7 @@
     public var hashValue: Int {
         #if arch(i386) || arch(arm)
             return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 16)))
-        #elseif arch(x86_64) || arch(arm64)
+        #elseif arch(x86_64) || arch(arm64) || arch(s390x)
             return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 32)))
         #endif
     }
@@ -261,8 +261,8 @@
         where R.Bound == S.Index, S.Index == String.Index {
             let r = region.relative(to: target)
             self = NSRange(
-                location: r.lowerBound._utf16Index - target.startIndex._utf16Index,
-                length: r.upperBound._utf16Index - r.lowerBound._utf16Index
+                location: r.lowerBound.encodedOffset - target.startIndex.encodedOffset,
+                length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset
             )
     }
     
diff --git a/Foundation/NSSortDescriptor.swift b/Foundation/NSSortDescriptor.swift
index 7a09d86..9bd70d8 100644
--- a/Foundation/NSSortDescriptor.swift
+++ b/Foundation/NSSortDescriptor.swift
@@ -35,10 +35,13 @@
     
     open var key: String? { NSUnimplemented() }
     open var ascending: Bool { NSUnimplemented() }
+    public var keyPath: AnyKeyPath? { NSUnimplemented() }
     
     open func allowEvaluation() { NSUnimplemented() } // Force a sort descriptor which was securely decoded to allow evaluation
     
     public init(key: String?, ascending: Bool, comparator cmptr: Comparator) { NSUnimplemented() }
+    public convenience init<Root, Value>(keyPath: KeyPath<Root, Value>, ascending: Bool) { NSUnimplemented() }
+    public convenience init<Root, Value>(keyPath: KeyPath<Root, Value>, ascending: Bool, comparator cmptr: @escaping Comparator) { NSUnimplemented() }
     
     open var comparator: Comparator { NSUnimplemented() }
     
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index 97212d5..5b43cf5 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -346,49 +346,7 @@
             let start = _storage.utf16.startIndex
             let min = start.advanced(by: range.location)
             let max = start.advanced(by: range.location + range.length)
-            if let substr = String(_storage.utf16[min..<max]) {
-                return substr
-            }
-            //If we come here, then the range has created unpaired surrogates on either end.
-            //An unpaired surrogate is replaced by OXFFFD - the Unicode Replacement Character.
-            //The CRLF ("\r\n") sequence is also treated like a surrogate pair, but its constinuent
-            //characters "\r" and "\n" can exist outside the pair!
-
-            let replacementCharacter = String(describing: UnicodeScalar(0xFFFD)!)
-            let CR: UInt16 = 13  //carriage return
-            let LF: UInt16 = 10  //new line
-
-            //make sure the range is of non-zero length
-            guard range.length > 0 else { return "" }
-
-            //if the range is pointing to a single unpaired surrogate
-            if range.length == 1 {
-                switch _storage.utf16[min] {
-                case CR: return "\r"
-                case LF: return "\n"
-                default: return replacementCharacter
-                }
-            }
-
-            //set the prefix and suffix characters
-            let prefix = _storage.utf16[min] == LF ? "\n" : replacementCharacter
-            let suffix = _storage.utf16[max.advanced(by: -1)] == CR ? "\r" : replacementCharacter
-
-            //if the range breaks a surrogate pair at the beginning of the string
-            if let substrSuffix = String(_storage.utf16[min.advanced(by: 1)..<max]) {
-                return prefix + substrSuffix
-            }
-
-            //if the range breaks a surrogate pair at the end of the string
-            if let substrPrefix = String(_storage.utf16[min..<max.advanced(by: -1)]) {
-                return substrPrefix + suffix
-            }
-
-            //the range probably breaks surrogate pairs at both the ends
-            guard min.advanced(by: 1) <= max.advanced(by: -1) else { return prefix + suffix }
-
-            let substr =  String(_storage.utf16[min.advanced(by: 1)..<max.advanced(by: -1)])!
-            return prefix + substr + suffix
+            return String(decoding: _storage.utf16[min..<max], as: UTF16.self)
         } else {
             let buff = UnsafeMutablePointer<unichar>.allocate(capacity: range.length)
             getCharacters(buff, range: range)
diff --git a/Foundation/NSStringAPI.swift b/Foundation/NSStringAPI.swift
index baa36f8..49d374a 100644
--- a/Foundation/NSStringAPI.swift
+++ b/Foundation/NSStringAPI.swift
@@ -30,8 +30,8 @@
 
 func _toNSRange(_ r: Range<String.Index>) -> NSRange {
   return NSRange(
-    location: r.lowerBound._utf16Index,
-    length: r.upperBound._utf16Index - r.lowerBound._utf16Index)
+    location: r.lowerBound.encodedOffset,
+    length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
 }
 
 extension String {
@@ -47,10 +47,7 @@
   /// Return an `Index` corresponding to the given offset in our UTF-16
   /// representation.
   func _index(_ utf16Index: Int) -> Index {
-    return Index(
-      _base: String.UnicodeScalarView.Index(_position: utf16Index),
-      in: characters
-    )
+    return Index(encodedOffset: utf16Index)
   }
 
   /// Return a `Range<Index>` corresponding to the given `NSRange` of
@@ -1076,7 +1073,7 @@
   public
   func rangeOfComposedCharacterSequence(at anIndex: Index) -> Range<Index> {
     return _range(
-      _ns.rangeOfComposedCharacterSequence(at: anIndex._utf16Index))
+      _ns.rangeOfComposedCharacterSequence(at: anIndex.encodedOffset))
   }
 
   // - (NSRange)rangeOfComposedCharacterSequencesForRange:(NSRange)range
@@ -1392,7 +1389,7 @@
   /// Returns a new string containing the characters of the
   /// `String` from the one at a given index to the end.
   public func substring(from index: Index) -> String {
-    return _ns.substring(from: index._utf16Index)
+    return _ns.substring(from: index.encodedOffset)
   }
 
   // - (NSString *)substringToIndex:(NSUInteger)anIndex
@@ -1400,7 +1397,7 @@
   /// Returns a new string containing the characters of the
   /// `String` up to, but not including, the one at a given index.
   public func substring(to index: Index) -> String {
-    return _ns.substring(to: index._utf16Index)
+    return _ns.substring(to: index.encodedOffset)
   }
 
   // - (NSString *)substringWithRange:(NSRange)aRange
diff --git a/Foundation/NSURLSession/NSURLSessionConfiguration.swift b/Foundation/NSURLSession/NSURLSessionConfiguration.swift
index 8ae00cd..70c3623 100644
--- a/Foundation/NSURLSession/NSURLSessionConfiguration.swift
+++ b/Foundation/NSURLSession/NSURLSessionConfiguration.swift
@@ -47,6 +47,7 @@
         self.urlCredentialStorage = nil
         self.urlCache = nil
         self.shouldUseExtendedBackgroundIdleMode = false
+        self.protocolClasses = [_HTTPURLProtocol.self]
         super.init()
     }
     
diff --git a/Foundation/NSURLSession/NSURLSessionTask.swift b/Foundation/NSURLSession/NSURLSessionTask.swift
index bcf06da..f819ff0 100644
--- a/Foundation/NSURLSession/NSURLSessionTask.swift
+++ b/Foundation/NSURLSession/NSURLSessionTask.swift
@@ -547,6 +547,11 @@
         guard let session = task.session as? URLSession else { fatalError() }
         switch session.behaviour(for: task) {
         case .taskDelegate(let delegate):
+            if let downloadDelegate = delegate as? URLSessionDownloadDelegate, let downloadTask = task as? URLSessionDownloadTask {
+                session.delegateQueue.addOperation {
+                    downloadDelegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: `protocol`.properties[URLProtocol._PropertyKey.temporaryFileURL] as! URL)
+                }
+            }
             session.delegateQueue.addOperation {
                 delegate.urlSession(session, task: task, didCompleteWithError: nil)
                 task.state = .completed
diff --git a/Foundation/NSURLSession/http/EasyHandle.swift b/Foundation/NSURLSession/http/EasyHandle.swift
index 2fe0ca1..4da41b5 100644
--- a/Foundation/NSURLSession/http/EasyHandle.swift
+++ b/Foundation/NSURLSession/http/EasyHandle.swift
@@ -52,11 +52,14 @@
 /// `Dispatch` only -- it is intentionally **not** thread safe.
 internal final class _EasyHandle {
     let rawHandle = CFURLSessionEasyHandleInit()
-    unowned let delegate: _EasyHandleDelegate
+    weak var delegate: _EasyHandleDelegate?
     fileprivate var headerList: _CurlStringList?
     fileprivate var pauseState: _PauseState = []
     internal var fileLength: Int64 = 0
     internal var timeoutTimer: _TimeoutSource!
+    #if os(Android)
+    static fileprivate var _CAInfoFile: UnsafeMutablePointer<Int8>?
+    #endif
 
     init(delegate: _EasyHandleDelegate) {
         self.delegate = delegate
@@ -88,7 +91,7 @@
 
 internal extension _EasyHandle {
     func completedTransfer(withErrorCode errorCode: Int?) {
-        delegate.transferCompleted(withErrorCode: errorCode)
+        delegate?.transferCompleted(withErrorCode: errorCode)
     }
 }
 internal protocol _EasyHandleDelegate: class {
@@ -168,6 +171,20 @@
         let protocols = (CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
         try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionPROTOCOLS, protocols).asError()
         try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols).asError()
+        #if os(Android)
+            // See https://curl.haxx.se/docs/sslcerts.html
+            // For SSL to work you need "cacert.pem" to be accessable
+            // at the path pointed to by the URLSessionCAInfo env var.
+            // Downloadable here: https://curl.haxx.se/ca/cacert.pem
+            if let caInfo = _EasyHandle._CAInfoFile  {
+                if String(cString: caInfo) == "UNSAFE_SSL_NOVERIFY" {
+                    try! CFURLSession_easy_setopt_int(rawHandle, CFURLSessionOptionSSL_VERIFYPEER, 0).asError()
+                }
+                else {
+                    try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, caInfo).asError()
+                }
+            }
+        #endif
         //TODO: Added in libcurl 7.45.0
         //TODO: Set default protocol for schemeless URLs
         //CURLOPT_DEFAULT_PROTOCOL available only in libcurl 7.45.0
@@ -268,7 +285,7 @@
 
 fileprivate func printLibcurlDebug(type: CFURLSessionInfo, data: String, task: URLSessionTask) {
     // libcurl sends is data with trailing CRLF which inserts lots of newlines into our output.
-    print("[\(task.taskIdentifier)] \(type.debugHeader) \(data.mapControlToPictures)")
+    NSLog("[\(task.taskIdentifier)] \(type.debugHeader) \(data.mapControlToPictures)")
 }
 
 fileprivate extension String {
@@ -479,12 +496,15 @@
     func didReceive(data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int) -> Int {
         let d: Int = {
             let buffer = Data(bytes: data, count: size*nmemb)
-            switch delegate.didReceive(data: buffer) {
-            case .proceed: return size * nmemb
-            case .abort: return 0
-            case .pause:
+            switch delegate?.didReceive(data: buffer) {
+            case .some(.proceed): return size * nmemb
+            case .some(.abort): return 0
+            case .some(.pause):
                 pauseState.insert(.receivePaused)
                 return Int(CFURLSessionWriteFuncPause)
+            case .none:
+                /* the delegate disappeared */
+                return 0
             }
         }()
         return d
@@ -497,12 +517,15 @@
         self.fileLength = Int64(fileLength)
         let d: Int = {
             let buffer = Data(bytes: data, count: size*nmemb)
-            switch delegate.didReceive(headerData: buffer) {
-            case .proceed: return size * nmemb
-            case .abort: return 0
-            case .pause:
+            switch delegate?.didReceive(headerData: buffer) {
+            case .some(.proceed): return size * nmemb
+            case .some(.abort): return 0
+            case .some(.pause):
                 pauseState.insert(.receivePaused)
                 return Int(CFURLSessionWriteFuncPause)
+            case .none:
+                /* the delegate disappeared */
+                return 0
             }
         }()
         return d
@@ -514,14 +537,17 @@
     func fill(writeBuffer data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int) -> Int {
         let d: Int = {
             let buffer = UnsafeMutableBufferPointer(start: data, count: size * nmemb)
-            switch delegate.fill(writeBuffer: buffer) {
-            case .pause:
+            switch delegate?.fill(writeBuffer: buffer) {
+            case .some(.pause):
                 pauseState.insert(.sendPaused)
                 return Int(CFURLSessionReadFuncPause)
-            case .abort:
+            case .some(.abort):
                 return Int(CFURLSessionReadFuncAbort)
-            case .bytes(let length):
+            case .some(.bytes(let length)):
                 return length 
+            case .none:
+                /* the delegate disappeared */
+                return Int(CFURLSessionReadFuncAbort)
             }
         }()
         return d
@@ -541,7 +567,7 @@
         //     <https://en.wikipedia.org/wiki/Quality_of_service>
     }
     func updateProgressMeter(with propgress: _Progress) {
-        delegate.updateProgressMeter(with: propgress)
+        delegate?.updateProgressMeter(with: propgress)
     }
     
     func seekInputStream(offset: Int64, origin: CInt) -> CInt {
@@ -549,8 +575,12 @@
             /// libcurl should only use SEEK_SET
             guard origin == SEEK_SET else { fatalError("Unexpected 'origin' in seek.") }
             do {
-                try delegate.seekInputStream(to: UInt64(offset))
-                return CFURLSessionSeekOk
+                if let delegate = delegate {
+                    try delegate.seekInputStream(to: UInt64(offset))
+                    return CFURLSessionSeekOk
+                } else {
+                    return CFURLSessionSeekCantSeek
+                }
             } catch {
                 return CFURLSessionSeekCantSeek
             }
@@ -602,6 +632,19 @@
     }
 }
 
+#if os(Android)
+extension URLSession {
+
+    public static func setCAInfoFile(_ _CAInfoFile: String) {
+        free(_EasyHandle._CAInfoFile)
+        _CAInfoFile.withCString {
+            _EasyHandle._CAInfoFile = strdup($0)
+        }
+    }
+
+}
+#endif
+
 extension CFURLSessionEasyCode : Equatable {
     public static func ==(lhs: CFURLSessionEasyCode, rhs: CFURLSessionEasyCode) -> Bool {
         return lhs.value == rhs.value
diff --git a/Foundation/NSURLSession/http/HTTPMessage.swift b/Foundation/NSURLSession/http/HTTPMessage.swift
index 8b82fb3..f8bff6f 100644
--- a/Foundation/NSURLSession/http/HTTPMessage.swift
+++ b/Foundation/NSURLSession/http/HTTPMessage.swift
@@ -222,7 +222,7 @@
     /// Split a request line into its 3 parts: *Method*, *Request-URI*, and *HTTP-Version*.
     /// - SeeAlso: https://tools.ietf.org/html/rfc2616#section-5.1
     func splitRequestLine() -> (String, String, String)? {
-        let scalars = self.unicodeScalars
+        let scalars = self.unicodeScalars[...]
         guard let firstSpace = scalars.rangeOfSpace else { return nil }
         let remainingRange = firstSpace.upperBound..<scalars.endIndex
         let remainder = scalars[remainingRange]
@@ -285,7 +285,7 @@
         // recipient MAY replace any linear white space with a single SP before
         // interpreting the field value or forwarding the message downstream.
         guard let (head, tail) = lines.decompose else { return nil }
-        let headView = head.unicodeScalars
+        let headView = head.unicodeScalars[...]
         guard let nameRange = headView.rangeOfTokenPrefix else { return nil }
         guard headView.index(after: nameRange.upperBound) <= headView.endIndex && headView[nameRange.upperBound] == _HTTPCharacters.Colon else { return nil }
         let name = String(headView[nameRange])
@@ -302,10 +302,10 @@
         }
         do {
             var t = tail
-            while t.first?.unicodeScalars.hasSPHTPrefix ?? false {
+            while t.first?.unicodeScalars[...].hasSPHTPrefix ?? false {
                 guard let (h2, t2) = t.decompose else { return nil }
                 t = t2
-                guard let v = h2.unicodeScalars.trimSPHTPrefix else { return nil }
+                guard let v = h2.unicodeScalars[...].trimSPHTPrefix else { return nil }
                 let valuePart = String(v)
                 value = value.map { $0 + " " + valuePart } ?? valuePart
             }
@@ -321,7 +321,7 @@
         return (head, tail)
     }
 }
-private extension String.UnicodeScalarView {
+private extension String.UnicodeScalarView.SubSequence {
     /// The range of *Token* characters as specified by RFC 2616.
     var rangeOfTokenPrefix: Range<Index>? {
         var end = startIndex
@@ -344,7 +344,7 @@
     }
     /// Unicode scalars after removing the leading spaces (SP) and horizontal tabs (HT).
     /// Returns `nil` if the unicode scalars do not start with a SP or HT.
-    var trimSPHTPrefix: String.UnicodeScalarView? {
+    var trimSPHTPrefix: SubSequence? {
         guard !isEmpty else { return nil }
         var idx = startIndex
         while idx < endIndex {
diff --git a/Foundation/NSURLSession/http/HTTPURLProtocol.swift b/Foundation/NSURLSession/http/HTTPURLProtocol.swift
index efb647b..b105b15 100644
--- a/Foundation/NSURLSession/http/HTTPURLProtocol.swift
+++ b/Foundation/NSURLSession/http/HTTPURLProtocol.swift
@@ -14,6 +14,8 @@
 
     fileprivate var easyHandle: _EasyHandle!
     fileprivate var totalDownloaded = 0
+    fileprivate var totalUploaded: Int64 = 0
+    fileprivate var requestBodyLength: Int64 = 0
     fileprivate var tempFileURL: URL
 
     public required init(task: URLSessionTask, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
@@ -127,6 +129,7 @@
                 set(requestBodyLength: .noBody)
             case (_, .some(let length)):
                 set(requestBodyLength: .length(length))
+                requestBodyLength = Int64(length)
             case (_, .none):
                 set(requestBodyLength: .unknown)
             }
@@ -439,8 +442,14 @@
 extension _HTTPURLProtocol: _EasyHandleDelegate {
     
     func didReceive(data: Data) -> _EasyHandle._Action {
-        guard case .transferInProgress(let ts) = internalState else { fatalError("Received body data, but no transfer in progress.") }
-        guard ts.isHeaderComplete else { fatalError("Received body data, but the header is not complete, yet.") }
+        guard case .transferInProgress(var ts) = internalState else { fatalError("Received body data, but no transfer in progress.") }
+        if !ts.isHeaderComplete {
+            ts.response = HTTPURLResponse(url: ts.url, statusCode: 200, httpVersion: "HTTP/0.9", headerFields: [:])
+            /* we received body data before CURL tells us that the headers are complete, that happens for HTTP/0.9 simple responses, see
+               - https://www.w3.org/Protocols/HTTP/1.0/spec.html#Message-Types
+               - https://github.com/curl/curl/issues/467
+            */
+        }
         notifyDelegate(aboutReceivedData: data)
         internalState = .transferInProgress(ts.byAppending(bodyData: data))
         return .proceed
@@ -449,13 +458,10 @@
     fileprivate func notifyDelegate(aboutReceivedData data: Data) {
         guard let t = self.task else { fatalError("Cannot notify") }
         if case .taskDelegate(let delegate) = t.session.behaviour(for: self.task!),
-            let dataDelegate = delegate as? URLSessionDataDelegate,
-            let task = self.task as? URLSessionDataTask {
-            // Forward to the delegate:
-            guard let s = self.task?.session as? URLSession else { fatalError() }
-            s.delegateQueue.addOperation {
-                dataDelegate.urlSession(s, dataTask: task, didReceive: data)
-            }
+            let _ = delegate as? URLSessionDataDelegate,
+            let _ = self.task as? URLSessionDataTask {
+            // Forward to protocol client:
+            self.client?.urlProtocol(self, didLoad: data)
         } else if case .taskDelegate(let delegate) = t.session.behaviour(for: self.task!),
             let downloadDelegate = delegate as? URLSessionDownloadDelegate,
             let task = self.task as? URLSessionDownloadTask {
@@ -471,9 +477,7 @@
             }
             if Int(self.easyHandle.fileLength) == self.totalDownloaded {
                 fileHandle.closeFile()
-                s.delegateQueue.addOperation {
-                    downloadDelegate.urlSession(s, downloadTask: task, didFinishDownloadingTo: self.tempFileURL)
-                }
+                self.properties[.temporaryFileURL] = self.tempFileURL
             }
         }
     }
@@ -494,6 +498,16 @@
         }
     }
 
+    fileprivate func notifyDelegate(aboutUploadedData count: Int64) {
+        let session = self.task?.session as! URLSession
+        guard case .taskDelegate(let delegate) = session.behaviour(for: self.task!), self.task is URLSessionUploadTask else { return }
+        totalUploaded += count
+        session.delegateQueue.addOperation {
+            delegate.urlSession(session, task: self.task!, didSendBodyData: count,
+                totalBytesSent: self.totalUploaded, totalBytesExpectedToSend: self.requestBodyLength)
+        }
+    }
+
     func fill(writeBuffer buffer: UnsafeMutableBufferPointer<Int8>) -> _EasyHandle._WriteBufferResult {
         guard case .transferInProgress(let ts) = internalState else { fatalError("Requested to fill write buffer, but transfer isn't in progress.") }
         guard let source = ts.requestBodySource else { fatalError("Requested to fill write buffer, but transfer state has no body source.") }
@@ -502,6 +516,7 @@
             copyDispatchData(data, infoBuffer: buffer)
             let count = data.count
             assert(count > 0)
+            notifyDelegate(aboutUploadedData: Int64(count))
             return .bytes(count)
         case .done:
             return .bytes(0)
@@ -759,14 +774,14 @@
     /// Whenever we receive a response (i.e. a complete header) from libcurl,
     /// this method gets called.
     func didReceiveResponse() {
-        guard let dt = task as? URLSessionDataTask else { return }
+        guard let _ = task as? URLSessionDataTask else { return }
         guard case .transferInProgress(let ts) = self.internalState else { fatalError("Transfer not in progress.") }
         guard let response = ts.response else { fatalError("Header complete, but not URL response.") }
         guard let session = task?.session as? URLSession else { fatalError() }
         switch session.behaviour(for: self.task!) {
         case .noDelegate:
             break
-        case .taskDelegate(let delegate as URLSessionDataDelegate):
+        case .taskDelegate(_):
             //TODO: There's a problem with libcurl / with how we're using it.
             // We're currently unable to pause the transfer / the easy handle:
             // https://curl.haxx.se/mail/lib-2016-03/0222.html
@@ -777,14 +792,8 @@
             case 301, 302, 303, 307:
                 break
             default:
-                session.delegateQueue.addOperation {
-                    delegate.urlSession(session, dataTask: dt, didReceive: response, completionHandler: { _ in
-                        URLSession.printDebug("warning: Ignoring disposition from completion handler.")
-                    })
-                }
+                self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
             }
-        case .taskDelegate:
-            break
         case .dataCompletionHandler:
             break
         case .downloadCompletionHandler:
diff --git a/Foundation/NSValue.swift b/Foundation/NSValue.swift
index 6b255d0..3971b21 100644
--- a/Foundation/NSValue.swift
+++ b/Foundation/NSValue.swift
@@ -154,3 +154,14 @@
     }
 }
 
+extension NSValue : _Factory {}
+
+internal protocol _Factory {
+    init(factory: () -> Self)
+}
+
+extension _Factory {
+    init(factory: () -> Self) {
+        self = factory()
+    }
+}
diff --git a/Foundation/NSXMLDTD.swift b/Foundation/NSXMLDTD.swift
index df55ada..5f3566b 100644
--- a/Foundation/NSXMLDTD.swift
+++ b/Foundation/NSXMLDTD.swift
@@ -22,7 +22,7 @@
         NSUnimplemented()
     }
     
-    public convenience init(contentsOf url: URL, options: Options = []) throws {
+    public convenience init(contentsOf url: URL, options mask: XMLNode.Options = []) throws {
         let urlString = url.absoluteString
 
         guard let node = _CFXMLParseDTD(urlString) else {
@@ -32,7 +32,7 @@
         self.init(ptr: node)
     }
 
-    public convenience init(data: Data, options: Options = []) throws {
+    public convenience init(data: Data, options mask: XMLNode.Options = []) throws {
         var unmanagedError: Unmanaged<CFError>? = nil
         
         guard let node = _CFXMLParseDTDFromData(data._cfObject, &unmanagedError) else {
@@ -52,7 +52,7 @@
     */
     open var publicID: String? {
         get {
-            return _CFXMLDTDExternalID(_xmlDTD)?._swiftObject
+            return _CFXMLDTDCopyExternalID(_xmlDTD)?._swiftObject
         }
 
         set {
@@ -70,7 +70,7 @@
     */
     open var systemID: String? {
         get {
-            return _CFXMLDTDSystemID(_xmlDTD)?._swiftObject
+            return _CFXMLDTDCopySystemID(_xmlDTD)?._swiftObject
         }
 
         set {
diff --git a/Foundation/NSXMLDTDNode.swift b/Foundation/NSXMLDTDNode.swift
index 6d28bb2..b8adaff 100644
--- a/Foundation/NSXMLDTDNode.swift
+++ b/Foundation/NSXMLDTDNode.swift
@@ -80,7 +80,7 @@
         super.init(ptr: ptr)
     } //primitive
     
-    public override init(kind: Kind, options: Options = []) {
+    public override init(kind: XMLNode.Kind, options: XMLNode.Options = []) {
         let ptr: _CFXMLNodePtr
 
         switch kind {
@@ -99,7 +99,7 @@
         @method dtdKind
         @abstract Sets the DTD sub kind.
     */
-    open var dtdKind: DTDKind {
+    open var dtdKind: XMLDTDNode.DTDKind {
         switch _CFXMLNodeGetType(_xmlNode) {
         case _kCFXMLDTDNodeTypeElement:
             switch _CFXMLDTDElementNodeGetType(_xmlNode) {
@@ -200,7 +200,7 @@
     */
     open var publicID: String? {
         get {
-            return _CFXMLDTDNodeGetPublicID(_xmlNode)?._swiftObject
+            return _CFXMLDTDNodeCopyPublicID(_xmlNode)?._swiftObject
         }
         set {
             if let value = newValue {
@@ -217,7 +217,7 @@
     */
     open var systemID: String? {
         get {
-            return _CFXMLDTDNodeGetSystemID(_xmlNode)?._swiftObject
+            return _CFXMLDTDNodeCopySystemID(_xmlNode)?._swiftObject
         }
         set {
             if let value = newValue {
@@ -238,7 +238,7 @@
                 return nil
             }
 
-            return _CFXMLGetEntityContent(_xmlNode)?._swiftObject
+            return _CFXMLCopyEntityContent(_xmlNode)?._swiftObject
         }
         set {
             guard dtdKind == .unparsed else {
diff --git a/Foundation/NSXMLDocument.swift b/Foundation/NSXMLDocument.swift
index ca82b6f..245ad1f 100644
--- a/Foundation/NSXMLDocument.swift
+++ b/Foundation/NSXMLDocument.swift
@@ -68,34 +68,34 @@
         @method initWithXMLString:options:error:
         @abstract Returns a document created from either XML or HTML, if the HTMLTidy option is set. Parse errors are returned in <tt>error</tt>.
     */
-    public convenience init(xmlString string: String, options: Options) throws {
+    public convenience init(xmlString string: String, options mask: XMLNode.Options = []) throws {
         guard let data = string.data(using: .utf8) else {
             // TODO: Throw an error
             fatalError("String: '\(string)' could not be converted to NSData using UTF-8 encoding")
         }
 
-        try self.init(data: data, options: options)
+        try self.init(data: data, options: mask)
     }
 
     /*!
         @method initWithContentsOfURL:options:error:
         @abstract Returns a document created from the contents of an XML or HTML URL. Connection problems such as 404, parse errors are returned in <tt>error</tt>.
     */
-    public convenience init(contentsOf url: URL, options: Options) throws {
+    public convenience init(contentsOf url: URL, options mask: XMLNode.Options = []) throws {
         let data = try Data(contentsOf: url, options: .mappedIfSafe)
 
-        try self.init(data: data, options: options)
+        try self.init(data: data, options: mask)
     }
 
     /*!
         @method initWithData:options:error:
         @abstract Returns a document created from data. Parse errors are returned in <tt>error</tt>.
     */
-    public init(data: Data, options: Options) throws {
-        let docPtr = _CFXMLDocPtrFromDataWithOptions(data._cfObject, Int32(options.rawValue))
+    public init(data: Data, options mask: XMLNode.Options = []) throws {
+        let docPtr = _CFXMLDocPtrFromDataWithOptions(data._cfObject, Int32(mask.rawValue))
         super.init(ptr: _CFXMLNodePtr(docPtr))
 
-        if options.contains(.documentValidate) {
+        if mask.contains(.documentValidate) {
             try validate()
         }
     }
@@ -124,7 +124,7 @@
     */
     open var characterEncoding: String? {
         get {
-            return _CFXMLDocCharacterEncoding(_xmlDoc)?._swiftObject
+            return _CFXMLDocCopyCharacterEncoding(_xmlDoc)?._swiftObject
         }
         set {
             if let value = newValue {
@@ -141,7 +141,7 @@
     */
     open var version: String? {
         get {
-            return _CFXMLDocVersion(_xmlDoc)?._swiftObject
+            return _CFXMLDocCopyVersion(_xmlDoc)?._swiftObject
         }
         set {
             if let value = newValue {
@@ -170,7 +170,7 @@
         @method documentContentKind
         @abstract The kind of document.
     */
-    open var documentContentKind: ContentKind  {
+    open var documentContentKind: XMLDocument.ContentKind  {
         get {
             let properties = _CFXMLDocProperties(_xmlDoc)
 
@@ -311,14 +311,14 @@
         @method XMLData
         @abstract Invokes XMLDataWithOptions with NSXMLNodeOptionsNone.
     */
-    /*@NSCopying*/ open var xmlData: Data { return xmlData(withOptions: []) }
+    /*@NSCopying*/ open var xmlData: Data { return xmlData() }
 
     /*!
         @method XMLDataWithOptions:
         @abstract The representation of this node as it would appear in an XML document, encoded based on characterEncoding.
     */
-    open func xmlData(withOptions options: Options) -> Data {
-        let string = xmlString(withOptions: options)
+    open func xmlData(options: XMLNode.Options = []) -> Data {
+        let string = xmlString(options: options)
         // TODO: support encodings other than UTF-8
 
         return string.data(using: .utf8) ?? Data()
diff --git a/Foundation/NSXMLElement.swift b/Foundation/NSXMLElement.swift
index aa12142..1b91296 100644
--- a/Foundation/NSXMLElement.swift
+++ b/Foundation/NSXMLElement.swift
@@ -27,9 +27,9 @@
         @method initWithName:URI:
         @abstract Returns an element whose full QName is specified.
     */
-    public init(name: String, uri: String?) {
+    public init(name: String, uri URI: String?) {
         super.init(kind: .element, options: [])
-        self.uri = uri
+        self.uri = URI
         self.name = name
     }
 
@@ -49,11 +49,18 @@
         @method initWithXMLString:error:
         @abstract Returns an element created from a string. Parse errors are collected in <tt>error</tt>.
     */
-    public init(xmlString string: String) throws {
-        NSUnimplemented()
+    public convenience init(xmlString string: String) throws {
+        // If we prepend the XML line to the string
+        let docString = """
+        <?xml version="1.0" encoding="utf-8" standalone="yes"?>\(string)
+        """
+        // we can use the document string parser to get the element
+        let doc = try XMLDocument(xmlString: docString, options: [])
+        // We know the doc has a root element and first child or else the above line would have thrown
+        self.init(ptr:  _CFXMLCopyNode(_CFXMLNodeGetFirstChild(doc._xmlNode)!, true))
     }
 
-    public convenience override init(kind: Kind, options: Options = []) {
+    public convenience override init(kind: XMLNode.Kind, options: XMLNode.Options = []) {
         self.init(name: "", uri: nil)
     }
 
@@ -69,17 +76,21 @@
         @method elementsForLocalName:URI
         @abstract Returns all of the child elements that match this localname URI pair.
     */
-    open func elements(forLocalName localName: String, uri: String?) -> [XMLElement] { NSUnimplemented() }
+    open func elements(forLocalName localName: String, uri URI: String?) -> [XMLElement] {
+        return self.filter({ _CFXMLNodeGetType($0._xmlNode) == _kCFXMLTypeElement }).filter({ $0.localName == localName && $0.uri == uri }).flatMap({ $0 as? XMLElement })
+    }
 
     /*!
         @method addAttribute:
         @abstract Adds an attribute. Attributes with duplicate names are not added.
     */
     open func addAttribute(_ attribute: XMLNode) {
-        let name = _CFXMLNodeGetName(attribute._xmlNode)!
-        let len = strlen(name)
-        name.withMemoryRebound(to: UInt8.self, capacity: Int(len)) {
-            guard _CFXMLNodeHasProp(_xmlNode, $0) == nil else { return }
+        guard let name = _CFXMLNodeCopyName(attribute._xmlNode)?._swiftObject else {
+            fatalError("Attributes must have a name!")
+        }
+
+        name.cString(using: .utf8)!.withUnsafeBufferPointer() {
+            guard let ptr = $0.baseAddress, _CFXMLNodeHasProp(_xmlNode, ptr) == nil else { return }
             addChild(attribute)
         }
     }
@@ -169,7 +180,7 @@
         @method attributeForLocalName:URI:
         @abstract Returns an attribute matching this localname URI pair.
     */
-    open func attribute(forLocalName localName: String, uri: String?) -> XMLNode? {
+    open func attribute(forLocalName localName: String, uri URI: String?) -> XMLNode? {
         NSUnimplemented()
     }
 
@@ -178,7 +189,10 @@
         @abstract Adds a namespace. Namespaces with duplicate names are not added.
     */
     open func addNamespace(_ aNamespace: XMLNode) {
-        NSUnimplemented()
+        if ((namespaces ?? []).flatMap({ $0.name }).contains(aNamespace.name ?? "")) {
+            return
+        }
+        _CFXMLAddNamespace(_xmlNode, aNamespace._xmlNode)
     }
 
     /*!
@@ -186,7 +200,7 @@
         @abstract Removes a namespace with a particular name.
     */
     open func removeNamespace(forPrefix name: String) {
-        NSUnimplemented()
+        _CFXMLRemoveNamespace(_xmlNode, name)
     }
 
     /*!
@@ -194,7 +208,28 @@
         @abstract Set the namespaces. In the case of duplicate names, the first namespace with the name is used.
     */
     open var namespaces: [XMLNode]? {
-        NSUnimplemented()
+        get {
+            var count: Int = 0
+            if let result = _CFXMLNamespaces(_xmlNode, &count) {
+                defer {
+                    free(result)
+                }
+                let namespacePtrs = UnsafeBufferPointer<_CFXMLNodePtr>(start: result, count: count)
+                return namespacePtrs.map { XMLNode._objectNodeForNode($0) }
+            }
+
+            return nil
+        }
+
+        set {
+            if var nodes = newValue?.map({ $0._xmlNode }) {
+                nodes.withUnsafeMutableBufferPointer({ (bufPtr) in
+                    _CFXMLSetNamespaces(_xmlNode, bufPtr.baseAddress, bufPtr.count)
+                })
+            } else {
+                _CFXMLSetNamespaces(_xmlNode, nil, 0);
+            }
+        }
     }
 
     /*!
diff --git a/Foundation/NSXMLNode.swift b/Foundation/NSXMLNode.swift
index 576b355..f240b3e 100644
--- a/Foundation/NSXMLNode.swift
+++ b/Foundation/NSXMLNode.swift
@@ -42,7 +42,7 @@
         case processingInstruction
         case comment
         case text
-        case dtd
+        case DTDKind
         case entityDeclaration
         case attributeDeclaration
         case elementDeclaration
@@ -52,26 +52,26 @@
     public struct Options : OptionSet {
         public let rawValue : UInt
         public init(rawValue: UInt) { self.rawValue = rawValue }
-        
+
         public static let nodeIsCDATA = Options(rawValue: 1 << 0)
         public static let nodeExpandEmptyElement = Options(rawValue: 1 << 1)
         public static let nodeCompactEmptyElement = Options(rawValue: 1 << 2)
         public static let nodeUseSingleQuotes = Options(rawValue: 1 << 3)
         public static let nodeUseDoubleQuotes = Options(rawValue: 1 << 4)
         public static let nodeNeverEscapeContents = Options(rawValue: 1 << 5)
-        
+
         public static let documentTidyHTML = Options(rawValue: 1 << 9)
         public static let documentTidyXML = Options(rawValue: 1 << 10)
         public static let documentValidate = Options(rawValue: 1 << 13)
-        
+
         public static let nodeLoadExternalEntitiesAlways = Options(rawValue: 1 << 14)
         public static let nodeLoadExternalEntitiesSameOriginOnly = Options(rawValue: 1 << 15)
         public static let nodeLoadExternalEntitiesNever = Options(rawValue: 1 << 19)
-        
+
         public static let documentXInclude = Options(rawValue: 1 << 16)
         public static let nodePrettyPrint = Options(rawValue: 1 << 17)
         public static let documentIncludeContentTypeDeclaration = Options(rawValue: 1 << 18)
-        
+
         public static let nodePreserveNamespaceOrder = Options(rawValue: 1 << 20)
         public static let nodePreserveAttributeOrder = Options(rawValue: 1 << 21)
         public static let nodePreserveEntities = Options(rawValue: 1 << 22)
@@ -101,7 +101,7 @@
         @method initWithKind:
         @abstract Invokes @link initWithKind:options: @/link with options set to NSXMLNodeOptionsNone
     */
-    public convenience init(kind: Kind) {
+    public convenience init(kind: XMLNode.Kind) {
         self.init(kind: kind, options: [])
     }
 
@@ -109,7 +109,7 @@
         @method initWithKind:options:
         @abstract Inits a node with fidelity options as description NSXMLNodeOptions.h
     */
-    public init(kind: Kind, options: Options = []) {
+    public init(kind: XMLNode.Kind, options: XMLNode.Options = []) {
 
         switch kind {
         case .document:
@@ -123,9 +123,12 @@
         case .attribute:
             _xmlNode = _CFXMLNodePtr(_CFXMLNewProperty(nil, "", ""))
 
-        case .dtd:
+        case .DTDKind:
             _xmlNode = _CFXMLNewDTD(nil, "", "", "")
-            
+
+        case .namespace:
+            _xmlNode = _CFXMLNewNamespace("", "")
+
         default:
             fatalError("invalid node kind for this initializer")
         }
@@ -216,7 +219,8 @@
         @abstract Returns a namespace <tt>xmlns:name="stringValue"</tt>.
     */
     open class func namespace(withName name: String, stringValue: String) -> Any {
-        NSUnimplemented()
+        let node = _CFXMLNewNamespace(name, stringValue)
+        return XMLNode(ptr: node)
     }
 
     /*!
@@ -260,7 +264,7 @@
         @method kind
         @abstract Returns an element, attribute, entity, or notation DTD node based on the full XML string.
     */
-    open var kind: Kind  {
+    open var kind: XMLNode.Kind  {
         switch _CFXMLNodeGetType(_xmlNode) {
         case _kCFXMLTypeElement:
             return .element
@@ -272,7 +276,7 @@
             return .document
 
         case _kCFXMLTypeDTD:
-            return .dtd
+            return .DTDKind
 
         case _kCFXMLDTDNodeTypeElement:
             return .elementDeclaration
@@ -286,6 +290,9 @@
         case _kCFXMLDTDNodeTypeAttribute:
             return .attributeDeclaration
 
+        case _kCFXMLTypeNamespace:
+            return .namespace
+
         default:
             return .invalid
         }
@@ -297,17 +304,21 @@
     */
     open var name: String? {
         get {
-            if let ptr = _CFXMLNodeGetName(_xmlNode) {
-                return String(cString: ptr)
-            } else {
-                return nil
+            if case .namespace = kind {
+                return _CFXMLNamespaceCopyPrefix(_xmlNode)?._swiftObject
             }
+
+            return _CFXMLNodeCopyName(_xmlNode)?._swiftObject
         }
         set {
-            if let newName = newValue {
-                _CFXMLNodeSetName(_xmlNode, newName)
+            if case .namespace = kind {
+                _CFXMLNamespaceSetPrefix(_xmlNode, newValue, Int64(newValue?.utf8.count ?? 0))
             } else {
-                _CFXMLNodeSetName(_xmlNode, "")
+                if let newName = newValue {
+                    _CFXMLNodeSetName(_xmlNode, newName)
+                } else {
+                    _CFXMLNodeSetName(_xmlNode, "")
+                }
             }
         }
     }
@@ -346,13 +357,25 @@
         get {
             switch kind {
             case .entityDeclaration:
-                return _CFXMLGetEntityContent(_CFXMLEntityPtr(_xmlNode))?._swiftObject
+                return _CFXMLCopyEntityContent(_CFXMLEntityPtr(_xmlNode))?._swiftObject
+
+            case .namespace:
+                return _CFXMLNamespaceCopyValue(_xmlNode)?._swiftObject
 
             default:
-                return _CFXMLNodeGetContent(_xmlNode)?._swiftObject
+                return _CFXMLNodeCopyContent(_xmlNode)?._swiftObject
             }
         }
         set {
+            if case .namespace = kind {
+                if let newValue = newValue {
+                    precondition(URL(string: newValue) != nil, "namespace stringValue must be a valid href")
+                }
+
+                _CFXMLNamespaceSetValue(_xmlNode, newValue, Int64(newValue?.utf8.count ?? 0))
+                return
+            }
+
             _removeAllChildNodesExceptAttributes() // in case anyone is holding a reference to any of these children we're about to destroy
 
             if let string = newValue {
@@ -428,7 +451,7 @@
                 entityPtr = _CFXMLGetParameterEntity(doc, entity)
             }
             if let validEntity = entityPtr {
-                let replacement = _CFXMLGetEntityContent(validEntity)?._swiftObject ?? ""
+                let replacement = _CFXMLCopyEntityContent(validEntity)?._swiftObject ?? ""
                 result.replaceSubrange(range, with: replacement.characters)
             } else {
                 result.replaceSubrange(range, with: []) // This appears to be how Darwin Foundation does it
@@ -503,7 +526,7 @@
             fallthrough
         case .element:
             fallthrough
-        case .dtd:
+        case .DTDKind:
             return Array<XMLNode>(self as XMLNode)
 
         default:
@@ -546,7 +569,7 @@
         @method previousNode:
         @abstract Returns the previous node in document order. This can be used to walk the tree backwards.
     */
-    /*@NSCopying*/ open var previousNode: XMLNode? {
+    /*@NSCopying*/ open var previous: XMLNode? {
         if let previousSibling = self.previousSibling {
             if let lastChild = _CFXMLNodeGetLastChild(previousSibling._xmlNode) {
                 return XMLNode._objectNodeForNode(lastChild)
@@ -564,7 +587,7 @@
         @method nextNode:
         @abstract Returns the next node in document order. This can be used to walk the tree forwards.
     */
-    /*@NSCopying*/ open var nextNode: XMLNode? {
+    /*@NSCopying*/ open var next: XMLNode? {
         if let children = _CFXMLNodeGetFirstChild(_xmlNode) {
             return XMLNode._objectNodeForNode(children)
         } else if let next = nextSibling {
@@ -585,7 +608,7 @@
         _CFXMLUnlinkNode(_xmlNode)
 
         guard let parentNodePtr = _CFXMLNodeGetPrivateData(parentPtr) else { return }
-        
+
         let parent: XMLNode = NSObject.unretainedReference(parentNodePtr)
         parent._childNodes.remove(self)
     }
@@ -597,53 +620,7 @@
     open var xPath: String? {
         guard _CFXMLNodeGetDocument(_xmlNode) != nil else { return nil }
 
-        var pathComponents: [String?] = []
-        var parent  = _CFXMLNodeGetParent(_xmlNode)
-        if parent != nil {
-            let parentObj = XMLNode._objectNodeForNode(parent!)
-            let siblingsWithSameName = parentObj.filter { $0.name == self.name }
-
-            if siblingsWithSameName.count > 1 {
-                guard let index = siblingsWithSameName.index(of: self) else { return nil }
-
-                pathComponents.append("\(self.name ?? "")[\(index + 1)]")
-            } else {
-                pathComponents.append(self.name)
-            }
-        } else {
-            return self.name
-        }
-        while true {
-            if let parentNode = _CFXMLNodeGetParent(parent!) {
-                let grandparent = XMLNode._objectNodeForNode(parentNode)
-                let possibleParentNodes = grandparent.filter { $0.name == self.parent?.name }
-                let count = possibleParentNodes.reduce(0) { (x, _) in
-                    return x + 1
-                }
-
-                if count <= 1 {
-                    pathComponents.append(XMLNode._objectNodeForNode(parent!).name)
-                } else {
-                    var parentNumber = 1
-                    for possibleParent in possibleParentNodes {
-                        if possibleParent == self.parent {
-                            break
-                        }
-                        parentNumber += 1
-                    }
-
-                    pathComponents.append("\(self.parent?.name ?? "")[\(parentNumber)]")
-                }
-
-                parent = _CFXMLNodeGetParent(parent!)
-
-            } else {
-                pathComponents.append(XMLNode._objectNodeForNode(parent!).name)
-                break
-            }
-        }
-
-        return pathComponents.reversed().flatMap({ return $0 }).joined(separator: "/")
+        return _CFXMLCopyPathForNode(_xmlNode)?._swiftObject
     }
 
     /*!
@@ -651,7 +628,7 @@
     	@abstract Returns the local name bar if this attribute or element's name is foo:bar
     */
     open var localName: String? {
-        return _CFXMLNodeLocalName(_xmlNode)?._swiftObject
+        return _CFXMLNodeCopyLocalName(_xmlNode)?._swiftObject
     }
 
     /*!
@@ -659,7 +636,7 @@
     	@abstract Returns the prefix foo if this attribute or element's name if foo:bar
     */
     open var prefix: String? {
-        return _CFXMLNodePrefix(_xmlNode)?._swiftObject
+        return _CFXMLNodeCopyPrefix(_xmlNode)?._swiftObject
     }
 
     /*!
@@ -668,7 +645,7 @@
     */
     open var uri: String? {
         get {
-            return _CFXMLNodeURI(_xmlNode)?._swiftObject
+            return _CFXMLNodeCopyURI(_xmlNode)?._swiftObject
         }
         set {
             if let URI = newValue {
@@ -728,15 +705,15 @@
         @abstract The representation of this node as it would appear in an XML document.
     */
     open var xmlString: String {
-        return xmlString(withOptions: [])
+        return xmlString(options: [])
     }
 
     /*!
         @method XMLStringWithOptions:
         @abstract The representation of this node as it would appear in an XML document, with various output options available.
     */
-    open func xmlString(withOptions options: Options) -> String {
-        return _CFXMLStringWithOptions(_xmlNode, UInt32(options.rawValue))._swiftObject
+    open func xmlString(options: Options) -> String {
+        return _CFXMLCopyStringWithOptions(_xmlNode, UInt32(options.rawValue))._swiftObject
     }
 
     /*!
@@ -788,12 +765,12 @@
         case .document:
             _CFXMLFreeDocument(_CFXMLDocPtr(_xmlNode))
 
-        case .dtd:
+        case .DTDKind:
             _CFXMLFreeDTD(_CFXMLDTDPtr(_xmlNode))
 
         case .attribute:
             _CFXMLFreeProperty(_xmlNode)
-            
+
         default:
             _CFXMLFreeNode(_xmlNode)
         }
@@ -809,7 +786,7 @@
             let parentNode = XMLNode._objectNodeForNode(parent)
             parentNode._childNodes.insert(self)
         }
-        
+
         withUnretainedReference {
             _CFXMLNodeSetPrivateData(_xmlNode, $0)
         }
@@ -968,4 +945,3 @@
         }
     }
 }
-
diff --git a/Foundation/NSXMLParser.swift b/Foundation/NSXMLParser.swift
index a2409f8..f36b07c 100644
--- a/Foundation/NSXMLParser.swift
+++ b/Foundation/NSXMLParser.swift
@@ -22,11 +22,10 @@
 
 extension XMLParser {
     public enum ExternalEntityResolvingPolicy : UInt {
-        
-        case resolveExternalEntitiesNever // default
-        case resolveExternalEntitiesNoNetwork
-        case resolveExternalEntitiesSameOriginOnly //only applies to NSXMLParser instances initialized with -initWithContentsOfURL:
-        case resolveExternalEntitiesAlways
+        case never // default
+        case noNetwork
+        case sameOriginOnly //only applies to NSXMLParser instances initialized with -initWithContentsOfURL:
+        case always
     }
 }
 
@@ -44,8 +43,8 @@
 
 private func UTF8STRING(_ bytes: UnsafePointer<UInt8>?) -> String? {
     guard let bytes = bytes else { return nil }
-    // strlen operates on the wrong type, char*. We can't rebind the memory to a different type without knowing it's length,
-    // but since we know strlen is in libc, its safe to directly bitcast the pointer without worrying about multiple accesses
+    // strlen operates on the wrong type, char*. We can't rebind the memory to a different type without knowing its length,
+    // but since we know strlen is in libc, it's safe to directly bitcast the pointer without worrying about multiple accesses
     // of different types visible to the compiler.
     let len = strlen(unsafeBitCast(bytes, to: UnsafePointer<Int8>.self))
     let str = String._fromCodeUnitSequence(UTF8.self, input: UnsafeBufferPointer(start: bytes, count: Int(len)))
@@ -75,7 +74,7 @@
         }
         if let url = a {
             let allowed = allowedEntityURLs.contains(url)
-            if allowed || policy != .resolveExternalEntitiesSameOriginOnly {
+            if allowed || policy != .sameOriginOnly {
                 if allowed {
                     return originalLoaderFunction(urlStr, identifier, context)
                 }
@@ -84,7 +83,7 @@
     }
     
     switch policy {
-    case .resolveExternalEntitiesSameOriginOnly:
+    case .sameOriginOnly:
         guard let url = parser._url else { break }
         
         if a == nil {
@@ -119,11 +118,11 @@
         if !matches {
             return nil
         }
-    case .resolveExternalEntitiesAlways:
+    case .always:
         break
-    case .resolveExternalEntitiesNever:
+    case .never:
         return nil
-    case .resolveExternalEntitiesNoNetwork:
+    case .noNetwork:
         return _CFXMLInterfaceNoNetExternalEntityLoader(urlStr, identifier, context)
     }
     
@@ -456,7 +455,7 @@
     open var shouldReportNamespacePrefixes: Bool = false
     
     //defaults to NSXMLNodeLoadExternalEntitiesNever
-    open var externalEntityResolvingPolicy: ExternalEntityResolvingPolicy = .resolveExternalEntitiesNever
+    open var externalEntityResolvingPolicy: ExternalEntityResolvingPolicy = .never
     
     open var allowedExternalEntityURLs: Set<URL>?
     
@@ -954,7 +953,7 @@
         
         case uriFragmentError
         
-        case nodtdError
+        case noDTDError
         
         case delegateAbortedParseError
     }
diff --git a/Foundation/NumberFormatter.swift b/Foundation/NumberFormatter.swift
index e702d29..3d4444a 100644
--- a/Foundation/NumberFormatter.swift
+++ b/Foundation/NumberFormatter.swift
@@ -895,16 +895,14 @@
         }
     }
     
-    // FIXME: Uncomment this when NSDecimalNumberHandler.default() gets rid of NSUnimplementend()
-    // This is currently commented out so that NSNumberFormatter instances can be tested
-//    internal var _roundingBehavior: NSDecimalNumberHandler = NSDecimalNumberHandler.default()
-//    /*@NSCopying*/ open var roundingBehavior: NSDecimalNumberHandler {
-//        get {
-//            return _roundingBehavior
-//        }
-//        set {
-//            _reset()
-//            _roundingBehavior = newValue
-//        }
-//    }
+    internal var _roundingBehavior: NSDecimalNumberHandler = NSDecimalNumberHandler.default
+    /*@NSCopying*/ open var roundingBehavior: NSDecimalNumberHandler {
+        get {
+            return _roundingBehavior
+        }
+        set {
+            _reset()
+            _roundingBehavior = newValue
+        }
+    }
 }
diff --git a/Foundation/Operation.swift b/Foundation/Operation.swift
index 988aef8..d74b2a8 100644
--- a/Foundation/Operation.swift
+++ b/Foundation/Operation.swift
@@ -48,7 +48,13 @@
     }
     
     open func start() {
+        lock.lock()
+        _executing = true
+        lock.unlock()
         main()
+        lock.lock()
+        _executing = false
+        lock.unlock()
         finish()
     }
     
@@ -85,7 +91,12 @@
     }
     
     open var isExecuting: Bool {
-        return _executing
+        let wasExecuting: Bool
+        lock.lock()
+        wasExecuting = _executing
+        lock.unlock()
+
+        return wasExecuting
     }
     
     open var isFinished: Bool {
@@ -306,7 +317,13 @@
     let lock = NSLock()
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
     var __concurrencyGate: DispatchSemaphore?
-    var __underlyingQueue: DispatchQueue?
+    var __underlyingQueue: DispatchQueue? {
+        didSet {
+            let key = OperationQueue.OperationQueueKey
+            oldValue?.setSpecific(key: key, value: nil)
+            __underlyingQueue?.setSpecific(key: key, value: Unmanaged.passUnretained(self))
+        }
+    }
     let queueGroup = DispatchGroup()
 #endif
     
@@ -552,29 +569,27 @@
 
     open class var current: OperationQueue? {
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
-        let specific = DispatchQueue.getSpecific(key: OperationQueue.OperationQueueKey)
-        if specific == nil {
+        guard let specific = DispatchQueue.getSpecific(key: OperationQueue.OperationQueueKey) else {
             if pthread_main_np() == 1 {
                 return OperationQueue.main
             } else {
                 return nil
             }
-        } else {
-            return specific!.takeUnretainedValue()
         }
+        
+        return specific.takeUnretainedValue()
 #else
         return nil
 #endif
     }
     
+#if DEPLOYMENT_ENABLE_LIBDISPATCH
+    private static let _main = OperationQueue(_queue: .main, maxConcurrentOperations: 1)
+#endif
+    
     open class var main: OperationQueue {
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
-        let specific = DispatchQueue.main.getSpecific(key: OperationQueue.OperationQueueKey)
-        if specific == nil {
-            return OperationQueue(_queue: DispatchQueue.main, maxConcurrentOperations: 1)
-        } else {
-            return specific!.takeUnretainedValue()
-        }
+        return _main
 #else
         fatalError("NSOperationQueue requires libdispatch")
 #endif
diff --git a/Foundation/PersonNameComponents.swift b/Foundation/PersonNameComponents.swift
index 2b8a934..c9fc5a0 100644
--- a/Foundation/PersonNameComponents.swift
+++ b/Foundation/PersonNameComponents.swift
@@ -137,3 +137,36 @@
         return AnyHashable(self._bridgeToSwift())
     }
 }
+
+extension PersonNameComponents : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case namePrefix
+        case givenName
+        case middleName
+        case familyName
+        case nameSuffix
+        case nickname
+    }
+    
+    public init(from decoder: Decoder) throws {
+        self.init()
+        
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        self.namePrefix = try container.decodeIfPresent(String.self, forKey: .namePrefix)
+        self.givenName  = try container.decodeIfPresent(String.self, forKey: .givenName)
+        self.middleName = try container.decodeIfPresent(String.self, forKey: .middleName)
+        self.familyName = try container.decodeIfPresent(String.self, forKey: .familyName)
+        self.nameSuffix = try container.decodeIfPresent(String.self, forKey: .nameSuffix)
+        self.nickname   = try container.decodeIfPresent(String.self, forKey: .nickname)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        if let np = self.namePrefix { try container.encode(np, forKey: .namePrefix) }
+        if let gn = self.givenName  { try container.encode(gn, forKey: .givenName) }
+        if let mn = self.middleName { try container.encode(mn, forKey: .middleName) }
+        if let fn = self.familyName { try container.encode(fn, forKey: .familyName) }
+        if let ns = self.nameSuffix { try container.encode(ns, forKey: .nameSuffix) }
+        if let nn = self.nickname   { try container.encode(nn, forKey: .nickname) }
+    }
+}
diff --git a/Foundation/Process.swift b/Foundation/Process.swift
index d104183..07a958e 100644
--- a/Foundation/Process.swift
+++ b/Foundation/Process.swift
@@ -387,11 +387,30 @@
             posix(posix_spawn_file_actions_addclose(&fileActions, fd))
         }
 
+        let fileManager = FileManager()
+        let previousDirectoryPath = fileManager.currentDirectoryPath
+        if !fileManager.changeCurrentDirectoryPath(currentDirectoryPath) {
+            // Foundation throws an NSException when changing the working directory fails,
+            // and unfortunately launch() is not marked `throws`, so we get away with a
+            // fatalError.
+            switch errno {
+            case ENOENT:
+                fatalError("Process: The specified working directory does not exist.")
+            case EACCES:
+                fatalError("Process: The specified working directory cannot be accessed.")
+            default:
+                fatalError("Process: The specified working directory cannot be set.")
+            }
+        }
+
         // Launch
 
         var pid = pid_t()
         posix(posix_spawn(&pid, launchPath, &fileActions, nil, argv, envp))
 
+        // Reset the previous working directory path.
+        fileManager.changeCurrentDirectoryPath(previousDirectoryPath)
+
         // Close the write end of the input and output pipes.
         if let pipe = standardInput as? Pipe {
             pipe.fileHandleForReading.closeFile()
diff --git a/Foundation/ProgressFraction.swift b/Foundation/ProgressFraction.swift
index 7dac53a..58a7147 100644
--- a/Foundation/ProgressFraction.swift
+++ b/Foundation/ProgressFraction.swift
@@ -54,7 +54,7 @@
         return _ProgressFraction(completed: simplified.0, total: simplified.1)
     }
     
-    static private func _math(lhs: _ProgressFraction, rhs: _ProgressFraction, whichOperator: (_ lhs : Double, _ rhs : Double) -> Double, whichOverflow : (_ lhs: Int64, _ rhs: Int64) -> (Int64, overflow: ArithmeticOverflow)) -> _ProgressFraction {
+    static private func _math(lhs: _ProgressFraction, rhs: _ProgressFraction, whichOperator: (_ lhs : Double, _ rhs : Double) -> Double, whichOverflow : (_ lhs: Int64, _ rhs: Int64) -> (Int64, overflow: Bool)) -> _ProgressFraction {
         // Mathematically, it is nonsense to add or subtract something with a denominator of 0. However, for the purposes of implementing Progress' fractions, we just assume that a zero-denominator fraction is "weightless" and return the other value. We still need to check for the case where they are both nonsense though.
         precondition(!(lhs.total == 0 && rhs.total == 0), "Attempt to add or subtract invalid fraction")
         guard lhs.total != 0 else {
@@ -71,7 +71,7 @@
 
         if let lcm = _leastCommonMultiple(lhs.total, rhs.total) {
             let result = whichOverflow(lhs.completed * (lcm / lhs.total), rhs.completed * (lcm / rhs.total))
-            if result.overflow == .overflow {
+            if result.overflow {
                 return _ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
             } else {
                 return _ProgressFraction(completed: result.0, total: lcm)
@@ -83,7 +83,7 @@
             
             if let lcm = _leastCommonMultiple(lhsSimplified.total, rhsSimplified.total) {
                 let result = whichOverflow(lhsSimplified.completed * (lcm / lhsSimplified.total), rhsSimplified.completed * (lcm / rhsSimplified.total))
-                if result.overflow == .overflow {
+                if result.overflow {
                     // Use original lhs/rhs here
                     return _ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
                 } else {
@@ -113,7 +113,7 @@
         let newCompleted = lhs.completed.multipliedReportingOverflow(by: rhs.completed)
         let newTotal = lhs.total.multipliedReportingOverflow(by: rhs.total)
         
-        if newCompleted.overflow == .overflow || newTotal.overflow == .overflow {
+        if newCompleted.overflow || newTotal.overflow {
             // Try simplifying, then do it again
             let lhsSimplified = lhs.simplified()
             let rhsSimplified = rhs.simplified()
@@ -121,7 +121,7 @@
             let newCompletedSimplified = lhsSimplified.completed.multipliedReportingOverflow(by: rhsSimplified.completed)
             let newTotalSimplified = lhsSimplified.total.multipliedReportingOverflow(by: rhsSimplified.total)
             
-            if newCompletedSimplified.overflow == .overflow || newTotalSimplified.overflow == .overflow {
+            if newCompletedSimplified.overflow || newTotalSimplified.overflow {
                 // Still overflow
                 return _ProgressFraction(double: lhs.fractionCompleted * rhs.fractionCompleted, overflow: true)
             } else {
@@ -140,12 +140,12 @@
         
         let newTotal = lhs.total.multipliedReportingOverflow(by: rhs)
         
-        if newTotal.overflow == .overflow {
+        if newTotal.overflow {
             let simplified = lhs.simplified()
             
             let newTotalSimplified = simplified.total.multipliedReportingOverflow(by: rhs)
             
-            if newTotalSimplified.overflow == .overflow {
+            if newTotalSimplified.overflow {
                 // Still overflow
                 return _ProgressFraction(double: lhs.fractionCompleted / Double(rhs), overflow: true)
             } else {
@@ -178,7 +178,7 @@
             let left = lhs.completed.multipliedReportingOverflow(by: rhs.total)
             let right = lhs.total.multipliedReportingOverflow(by: rhs.completed)
             
-            if left.overflow == .none && right.overflow == .none {
+            if !left.overflow && !right.overflow {
                 if left.0 == right.0 {
                     return true
                 }
@@ -190,7 +190,7 @@
                 let leftSimplified = lhsSimplified.completed.multipliedReportingOverflow(by: rhsSimplified.total)
                 let rightSimplified = lhsSimplified.total.multipliedReportingOverflow(by: rhsSimplified.completed)
 
-                if leftSimplified.overflow == .none && rightSimplified.overflow == .none {
+                if !leftSimplified.overflow && !rightSimplified.overflow {
                     if leftSimplified.0 == rightSimplified.0 {
                         return true
                     }
@@ -261,7 +261,7 @@
         // This division always results in an integer value because gcd(a,b) is a divisor of a.
         // lcm(a,b) == (|a|/gcd(a,b))*b == (|b|/gcd(a,b))*a
         let result = (a / _greatestCommonDivisor(a, b)).multipliedReportingOverflow(by: b)
-        if result.overflow == .overflow {
+        if result.overflow {
             return nil
         } else {
             return result.0
diff --git a/Foundation/URLComponents.swift b/Foundation/URLComponents.swift
index fdf6d95..16bcabb 100644
--- a/Foundation/URLComponents.swift
+++ b/Foundation/URLComponents.swift
@@ -188,8 +188,8 @@
     private func _toStringRange(_ r : NSRange) -> Range<String.Index>? {
         guard r.location != NSNotFound else { return nil }
         
-        let utf16Start = String.UTF16View.Index(_offset: r.location)
-        let utf16End = String.UTF16View.Index(_offset: r.location + r.length)
+        let utf16Start = String.UTF16View.Index(encodedOffset: r.location)
+        let utf16End = String.UTF16View.Index(encodedOffset: r.location + r.length)
         
         guard let s = self.string else { return nil }
         guard let start = String.Index(utf16Start, within: s) else { return nil }
diff --git a/Foundation/UUID.swift b/Foundation/UUID.swift
index 269a9a2..9b51302 100644
--- a/Foundation/UUID.swift
+++ b/Foundation/UUID.swift
@@ -163,3 +163,21 @@
     }
 }
 
+extension UUID : Codable {
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.singleValueContainer()
+        let uuidString = try container.decode(String.self)
+        
+        guard let uuid = UUID(uuidString: uuidString) else {
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath,
+                                                                    debugDescription: "Attempted to decode UUID from invalid UUID string."))
+        }
+        
+        self = uuid
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.singleValueContainer()
+        try container.encode(self.uuidString)
+    }
+}
diff --git a/TestFoundation/HTTPServer.swift b/TestFoundation/HTTPServer.swift
index bec7079..b129f74 100644
--- a/TestFoundation/HTTPServer.swift
+++ b/TestFoundation/HTTPServer.swift
@@ -17,10 +17,12 @@
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
     import Foundation
     import Glibc
+    import XCTest
 #else
     import CoreFoundation
     import SwiftFoundation
     import Darwin
+    import SwiftXCTest
 #endif
 
 public let globalDispatchQueue = DispatchQueue.global()
@@ -104,6 +106,12 @@
             return String(str[startIndex..<endIndex])
         }
     }
+
+    func writeRawData(_ data: Data) throws {
+        _ = try data.withUnsafeBytes { ptr in
+            try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, ptr, data.count)))
+        }
+    }
    
     func writeData(header: String, body: String, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
         var header = Array(header.utf8)
@@ -173,6 +181,69 @@
         semaphore.wait()
         
     } 
+
+    func respondWithBrokenResponses(uri: String) throws {
+        let responseData: Data
+        switch uri {
+            case "/LandOfTheLostCities/Pompeii":
+                /* this is an example of what you get if you connect to an HTTP2
+                 server using HTTP/1.1. Curl interprets that as a HTTP/0.9
+                 simple-response and therefore sends this back as a response
+                 body. Go figure! */
+                responseData = Data(bytes: [
+                    0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                    0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+                    0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x00, 0x00, 0x06, 0x00,
+                    0x00, 0x1f, 0x40, 0x00, 0x00, 0x86, 0x07, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                    0x48, 0x54, 0x54, 0x50, 0x2f, 0x32, 0x20, 0x63, 0x6c, 0x69,
+                    0x65, 0x6e, 0x74, 0x20, 0x70, 0x72, 0x65, 0x66, 0x61, 0x63,
+                    0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6d,
+                    0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20,
+                    0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x2e, 0x20, 0x48,
+                    0x65, 0x78, 0x20, 0x64, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6f,
+                    0x72, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+                    0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x3a, 0x20, 0x34, 0x37,
+                    0x34, 0x35, 0x35, 0x34, 0x32, 0x30, 0x32, 0x66, 0x33, 0x33,
+                    0x32, 0x66, 0x36, 0x34, 0x36, 0x35, 0x37, 0x36, 0x36, 0x39,
+                    0x36, 0x33, 0x36, 0x35, 0x32, 0x66, 0x33, 0x31, 0x33, 0x32,
+                    0x33, 0x33, 0x33, 0x34, 0x33, 0x35, 0x33, 0x36, 0x33, 0x37,
+                    0x33, 0x38, 0x33, 0x39, 0x33, 0x30])
+            case "/LandOfTheLostCities/Sodom":
+                /* a technically valid HTTP/0.9 simple-response */
+                responseData = ("technically, this is a valid HTTP/0.9 " +
+                    "simple-response. I know it's odd but CURL supports it " +
+                    "still...\r\nFind out more in those URLs:\r\n " +
+                    " - https://www.w3.org/Protocols/HTTP/1.0/spec.html#Message-Types\r\n" +
+                    " - https://github.com/curl/curl/issues/467\r\n").data(using: .utf8)!
+            case "/LandOfTheLostCities/Gomorrah":
+                /* just broken, hope that's not officially HTTP/0.9 :p */
+                responseData = "HTTP/1.1\r\n\r\n\r\n".data(using: .utf8)!
+            case "/LandOfTheLostCities/Myndus":
+                responseData = ("HTTP/1.1 200 OK\r\n" +
+                               "\r\n" +
+                               "this is a body that isn't legal as it's " +
+                               "neither chunked encoding nor any Content-Length\r\n").data(using: .utf8)!
+            case "/LandOfTheLostCities/Kameiros":
+                responseData = ("HTTP/1.1 999 Wrong Code\r\n" +
+                               "illegal: status code (too large)\r\n" +
+                               "\r\n").data(using: .utf8)!
+            case "/LandOfTheLostCities/Dinavar":
+                responseData = ("HTTP/1.1 20 Too Few Digits\r\n" +
+                               "illegal: status code (too few digits)\r\n" +
+                               "\r\n").data(using: .utf8)!
+            case "/LandOfTheLostCities/Kuhikugu":
+                responseData = ("HTTP/1.1 2000 Too Many Digits\r\n" +
+                               "illegal: status code (too many digits)\r\n" +
+                               "\r\n").data(using: .utf8)!
+            default:
+                responseData = ("HTTP/1.1 500 Internal Server Error\r\n" +
+                               "case-missing-in: TestFoundation/HTTPServer.swift\r\n" +
+                               "\r\n").data(using: .utf8)!
+        }
+        try self.socket.writeRawData(responseData)
+    }
+
 }
 
 struct _HTTPRequest {
@@ -249,11 +320,17 @@
     }
    
     public func readAndRespond() throws {
-        try httpServer.respond(with: process(request: httpServer.request()), startDelay: self.startDelay, sendDelay: self.sendDelay, bodyChunks: self.bodyChunks)
+        let req = try httpServer.request()
+        if req.uri.hasPrefix("/LandOfTheLostCities/") {
+            /* these are all misbehaving servers */
+            try httpServer.respondWithBrokenResponses(uri: req.uri)
+        } else {
+            try httpServer.respond(with: process(request: req), startDelay: self.startDelay, sendDelay: self.sendDelay, bodyChunks: self.bodyChunks)
+        }
     }
 
     func process(request: _HTTPRequest) -> _HTTPResponse {
-        if request.method == .GET || request.method == .POST {
+        if request.method == .GET || request.method == .POST || request.method == .PUT {
             return getResponse(request: request)
         } else {
             fatalError("Unsupported method!")
@@ -262,14 +339,20 @@
 
     func getResponse(request: _HTTPRequest) -> _HTTPResponse {
         let uri = request.uri
+
+        if uri == "/upload" {
+            let text = "Upload completed!"
+            return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.data(using: .utf8)!.count)", body: text)
+        }
+
         if uri == "/country.txt" {
             let text = capitals[String(uri.characters.dropFirst())]!
-            return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.characters.count)", body: text)
+            return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.data(using: .utf8)!.count)", body: text)
         }
 
         if uri == "/requestHeaders" {
             let text = request.getCommaSeparatedHeaders()
-            return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.characters.count)", body: text)
+            return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.data(using: .utf8)!.count)", body: text)
         }
 
 	if uri == "/UnitedStates" {
@@ -319,3 +402,39 @@
         dispatchSemaphore.signal()
     }
 }
+
+class LoopbackServerTest : XCTestCase {
+    static var serverPort: Int = -1
+
+    override class func setUp() {
+        super.setUp()
+        func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
+            let start = 21961
+            for port in start...(start+100) { //we must find at least one port to bind
+                do {
+                    serverPort = port
+                    let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
+                    try test.start(started: condition)
+                    try test.readAndRespond()
+                    test.stop()
+                } catch let e as ServerError {
+                    if e.operation == "bind" { continue }
+                    throw e
+                }
+            }
+        }
+
+        let serverReady = ServerSemaphore()
+        globalDispatchQueue.async {
+            do {
+                try runServer(with: serverReady)
+
+            } catch {
+                XCTAssertTrue(true)
+                return
+            }
+        }
+
+        serverReady.wait()
+    }
+}
diff --git a/TestFoundation/TestCodable.swift b/TestFoundation/TestCodable.swift
new file mode 100644
index 0000000..0ff8297
--- /dev/null
+++ b/TestFoundation/TestCodable.swift
@@ -0,0 +1,328 @@
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+
+#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
+import Foundation
+import XCTest
+#else
+import SwiftFoundation
+import SwiftXCTest
+#endif
+
+// MARK: - Helper Functions
+
+private func makePersonNameComponents(namePrefix: String? = nil,
+                                      givenName: String? = nil,
+                                      middleName: String? = nil,
+                                      familyName: String? = nil,
+                                      nameSuffix: String? = nil,
+                                      nickname: String? = nil) -> PersonNameComponents {
+    var result = PersonNameComponents()
+    result.namePrefix = namePrefix
+    result.givenName = givenName
+    result.middleName = middleName
+    result.familyName = familyName
+    result.nameSuffix = nameSuffix
+    result.nickname = nickname
+    return result
+}
+
+func expectRoundTripEquality<T : Codable>(of value: T, encode: (T) throws -> Data, decode: (Data) throws -> T) where T : Equatable {
+    let data: Data
+    do {
+        data = try encode(value)
+    } catch {
+        fatalError("Unable to encode \(T.self) <\(value)>: \(error)")
+    }
+
+    let decoded: T
+    do {
+        decoded = try decode(data)
+    } catch {
+        fatalError("Unable to decode \(T.self) <\(value)>: \(error)")
+    }
+
+    XCTAssertEqual(value, decoded, "Decoded \(T.self) <\(decoded)> not equal to original <\(value)>")
+}
+
+func expectRoundTripEqualityThroughJSON<T : Codable>(for value: T) where T : Equatable {
+    let inf = "INF", negInf = "-INF", nan = "NaN"
+    let encode = { (_ value: T) throws -> Data in
+        let encoder = JSONEncoder()
+        encoder.nonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: inf,
+                                                                      negativeInfinity: negInf,
+                                                                      nan: nan)
+        return try encoder.encode(value)
+    }
+
+    let decode = { (_ data: Data) throws -> T in
+        let decoder = JSONDecoder()
+        decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: inf,
+                                                                        negativeInfinity: negInf,
+                                                                        nan: nan)
+        return try decoder.decode(T.self, from: data)
+    }
+
+    expectRoundTripEquality(of: value, encode: encode, decode: decode)
+}
+
+// MARK: - Helper Types
+// A wrapper around a UUID that will allow it to be encoded at the top level of an encoder.
+struct UUIDCodingWrapper : Codable, Equatable {
+    let value: UUID
+
+    init(_ value: UUID) {
+        self.value = value
+    }
+
+    static func ==(_ lhs: UUIDCodingWrapper, _ rhs: UUIDCodingWrapper) -> Bool {
+        return lhs.value == rhs.value
+    }
+}
+
+// MARK: - Tests
+class TestCodable : XCTestCase {
+
+    // MARK: - PersonNameComponents
+    lazy var personNameComponentsValues: [PersonNameComponents] = [
+        makePersonNameComponents(givenName: "John", familyName: "Appleseed"),
+        makePersonNameComponents(givenName: "John", familyName: "Appleseed", nickname: "Johnny"),
+        makePersonNameComponents(namePrefix: "Dr.", givenName: "Jane", middleName: "A.", familyName: "Appleseed", nameSuffix: "Esq.", nickname: "Janie")
+    ]
+
+    func test_PersonNameComponents_JSON() {
+        for components in personNameComponentsValues {
+            expectRoundTripEqualityThroughJSON(for: components)
+        }
+    }
+
+    // MARK: - UUID
+    lazy var uuidValues: [UUID] = [
+        UUID(),
+        UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!,
+        UUID(uuidString: "e621e1f8-c36c-495a-93fc-0c247a3e6e5f")!,
+        UUID(uuid: uuid_t(0xe6,0x21,0xe1,0xf8,0xc3,0x6c,0x49,0x5a,0x93,0xfc,0x0c,0x24,0x7a,0x3e,0x6e,0x5f))
+    ]
+
+    func test_UUID_JSON() {
+        for uuid in uuidValues {
+            // We have to wrap the UUID since we cannot have a top-level string.
+            expectRoundTripEqualityThroughJSON(for: UUIDCodingWrapper(uuid))
+        }
+    }
+
+    // MARK: - URL
+    lazy var urlValues: [URL] = [
+        URL(fileURLWithPath: NSTemporaryDirectory()),
+        URL(fileURLWithPath: "/"),
+        URL(string: "http://apple.com")!,
+        URL(string: "swift", relativeTo: URL(string: "http://apple.com")!)!,
+        URL(fileURLWithPath: "bin/sh", relativeTo: URL(fileURLWithPath: "/"))
+    ]
+
+    func test_URL_JSON() {
+        for url in urlValues {
+            expectRoundTripEqualityThroughJSON(for: url)
+        }
+    }
+
+    // MARK: - NSRange
+    lazy var nsrangeValues: [NSRange] = [
+        NSRange(),
+        NSRange(location: 0, length: Int.max),
+        NSRange(location: NSNotFound, length: 0),
+        ]
+
+    func test_NSRange_JSON() {
+        for range in nsrangeValues {
+            expectRoundTripEqualityThroughJSON(for: range)
+        }
+    }
+
+    // MARK: - Locale
+    lazy var localeValues: [Locale] = [
+        Locale(identifier: ""),
+        Locale(identifier: "en"),
+        Locale(identifier: "en_US"),
+        Locale(identifier: "en_US_POSIX"),
+        Locale(identifier: "uk"),
+        Locale(identifier: "fr_FR"),
+        Locale(identifier: "fr_BE"),
+        Locale(identifier: "zh-Hant-HK")
+    ]
+
+    func test_Locale_JSON() {
+        for locale in localeValues {
+            expectRoundTripEqualityThroughJSON(for: locale)
+        }
+    }
+
+    // MARK: - IndexSet
+    lazy var indexSetValues: [IndexSet] = [
+        IndexSet(),
+        IndexSet(integer: 42),
+        IndexSet(integersIn: 0 ..< Int.max)
+    ]
+
+    func test_IndexSet_JSON() {
+        for indexSet in indexSetValues {
+            expectRoundTripEqualityThroughJSON(for: indexSet)
+        }
+    }
+
+    // MARK: - IndexPath
+    lazy var indexPathValues: [IndexPath] = [
+        IndexPath(), // empty
+        IndexPath(index: 0), // single
+        IndexPath(indexes: [1, 2]), // pair
+        IndexPath(indexes: [3, 4, 5, 6, 7, 8]), // array
+    ]
+
+    func test_IndexPath_JSON() {
+        for indexPath in indexPathValues {
+            expectRoundTripEqualityThroughJSON(for: indexPath)
+        }
+    }
+
+    // MARK: - AffineTransform
+    lazy var affineTransformValues: [AffineTransform] = [
+        AffineTransform.identity,
+        AffineTransform(),
+        AffineTransform(translationByX: 2.0, byY: 2.0),
+        AffineTransform(scale: 2.0),
+
+        // Disabled due to a bug: JSONSerialization loses precision for m12 and m21
+        // 0.02741213359204429 is serialized to 0.0274121335920443
+        //        AffineTransform(rotationByDegrees: .pi / 2),
+
+        AffineTransform(m11: 1.0, m12: 2.5, m21: 66.2, m22: 40.2, tX: -5.5, tY: 3.7),
+        AffineTransform(m11: -55.66, m12: 22.7, m21: 1.5, m22: 0.0, tX: -22, tY: -33),
+        AffineTransform(m11: 4.5, m12: 1.1, m21: 0.025, m22: 0.077, tX: -0.55, tY: 33.2),
+        AffineTransform(m11: 7.0, m12: -2.3, m21: 6.7, m22: 0.25, tX: 0.556, tY: 0.99),
+        AffineTransform(m11: 0.498, m12: -0.284, m21: -0.742, m22: 0.3248, tX: 12, tY: 44)
+    ]
+
+    func test_AffineTransform_JSON() {
+        for transform in affineTransformValues {
+            expectRoundTripEqualityThroughJSON(for: transform)
+        }
+    }
+
+    // MARK: - Decimal
+    lazy var decimalValues: [Decimal] = [
+        Decimal.leastFiniteMagnitude,
+        Decimal.greatestFiniteMagnitude,
+        Decimal.leastNormalMagnitude,
+        Decimal.leastNonzeroMagnitude,
+        Decimal.pi,
+        Decimal()
+    ]
+
+    func test_Decimal_JSON() {
+        for decimal in decimalValues {
+            expectRoundTripEqualityThroughJSON(for: decimal)
+        }
+    }
+    
+    // MARK: - CGPoint
+    lazy var cgpointValues: [CGPoint] = [
+        CGPoint(),
+        CGPoint.zero,
+        CGPoint(x: 10, y: 20),
+        CGPoint(x: -10, y: -20),
+        // Disabled due to limit on magnitude in JSON. See SR-5346
+        // CGPoint(x: .greatestFiniteMagnitude, y: .greatestFiniteMagnitude),
+    ]
+    
+    func test_CGPoint_JSON() {
+        for point in cgpointValues {
+            expectRoundTripEqualityThroughJSON(for: point)
+        }
+    }
+    
+    // MARK: - CGSize
+    lazy var cgsizeValues: [CGSize] = [
+        CGSize(),
+        CGSize.zero,
+        CGSize(width: 30, height: 40),
+        CGSize(width: -30, height: -40),
+        // Disabled due to limit on magnitude in JSON. See SR-5346
+        // CGSize(width: .greatestFiniteMagnitude, height: .greatestFiniteMagnitude),
+    ]
+    
+    func test_CGSize_JSON() {
+        for size in cgsizeValues {
+            expectRoundTripEqualityThroughJSON(for: size)
+        }
+    }
+    
+    // MARK: - CGRect
+    lazy var cgrectValues: [CGRect] = [
+        CGRect(),
+        CGRect.zero,
+        CGRect(origin: CGPoint(x: 10, y: 20), size: CGSize(width: 30, height: 40)),
+        CGRect(origin: CGPoint(x: -10, y: -20), size: CGSize(width: -30, height: -40)),
+        CGRect.null,
+        // Disabled due to limit on magnitude in JSON. See SR-5346
+        // CGRect.infinite
+    ]
+    
+    func test_CGRect_JSON() {
+        for rect in cgrectValues {
+            expectRoundTripEqualityThroughJSON(for: rect)
+        }
+    }
+    
+    // MARK: - CharacterSet
+    lazy var characterSetValues: [CharacterSet] = [
+        CharacterSet.controlCharacters,
+        CharacterSet.whitespaces,
+        CharacterSet.whitespacesAndNewlines,
+        CharacterSet.decimalDigits,
+        CharacterSet.letters,
+        CharacterSet.lowercaseLetters,
+        CharacterSet.uppercaseLetters,
+        CharacterSet.nonBaseCharacters,
+        CharacterSet.alphanumerics,
+        CharacterSet.decomposables,
+        CharacterSet.illegalCharacters,
+        CharacterSet.punctuationCharacters,
+        CharacterSet.capitalizedLetters,
+        CharacterSet.symbols,
+        CharacterSet.newlines,
+        CharacterSet(charactersIn: "abcd")
+    ]
+    
+    func test_CharacterSet_JSON() {
+        for characterSet in characterSetValues {
+            expectRoundTripEqualityThroughJSON(for: characterSet)
+        }
+    }
+
+}
+
+extension TestCodable {
+    static var allTests: [(String, (TestCodable) -> () throws -> Void)] {
+        return [
+            ("test_PersonNameComponents_JSON", test_PersonNameComponents_JSON),
+            ("test_UUID_JSON", test_UUID_JSON),
+            ("test_URL_JSON", test_URL_JSON),
+            ("test_NSRange_JSON", test_NSRange_JSON),
+            ("test_Locale_JSON", test_Locale_JSON),
+            ("test_IndexSet_JSON", test_IndexSet_JSON),
+            ("test_IndexPath_JSON", test_IndexPath_JSON),
+            ("test_AffineTransform_JSON", test_AffineTransform_JSON),
+            ("test_Decimal_JSON", test_Decimal_JSON),
+            ("test_CGPoint_JSON", test_CGPoint_JSON),
+            ("test_CGSize_JSON", test_CGSize_JSON),
+            ("test_CGRect_JSON", test_CGRect_JSON),
+            ("test_CharacterSet_JSON", test_CharacterSet_JSON),
+        ]
+    }
+}
diff --git a/TestFoundation/TestFileManager.swift b/TestFoundation/TestFileManager.swift
index ab43967..a9cb932 100644
--- a/TestFoundation/TestFileManager.swift
+++ b/TestFoundation/TestFileManager.swift
@@ -84,6 +84,29 @@
         } catch {
             XCTFail("Failed to clean up file")
         }
+
+        let permissions = NSNumber(value: Int16(0o753))
+        let attributes = [FileAttributeKey.posixPermissions: permissions]
+        XCTAssertTrue(fm.createFile(atPath: path, contents: Data(),
+                                    attributes: attributes))
+        guard let retrievedAtributes = try? fm.attributesOfItem(atPath: path) else {
+            XCTFail("Failed to retrieve file attributes from created file")
+            return
+        }
+
+        XCTAssertTrue(retrievedAtributes.contains(where: { (attribute) -> Bool in
+            guard let attributeValue = attribute.value as? NSNumber else {
+                return false
+            }
+            return (attribute.key == .posixPermissions)
+                && (attributeValue == permissions)
+        }))
+
+        do {
+            try fm.removeItem(atPath: path)
+        } catch {
+            XCTFail("Failed to clean up file")
+        }
     }
 
     func test_moveFile() {
diff --git a/TestFoundation/TestJSONEncoder.swift b/TestFoundation/TestJSONEncoder.swift
index 212a0b3..8631442 100644
--- a/TestFoundation/TestJSONEncoder.swift
+++ b/TestFoundation/TestJSONEncoder.swift
@@ -693,6 +693,28 @@
 
 // MARK: - Helper Types
 
+/// A key type which can take on any string or integer value.
+/// This needs to mirror _JSONKey.
+fileprivate struct _TestKey : CodingKey {
+  var stringValue: String
+  var intValue: Int?
+
+  init?(stringValue: String) {
+    self.stringValue = stringValue
+    self.intValue = nil
+  }
+
+  init?(intValue: Int) {
+    self.stringValue = "\(intValue)"
+    self.intValue = intValue
+  }
+
+  init(index: Int) {
+    self.stringValue = "Index \(index)"
+    self.intValue = index
+  }
+}
+
 /// Wraps a type T so that it can be encoded at the top level of a payload.
 fileprivate struct TopLevelArrayWrapper<T> : Codable, Equatable where T : Codable, T : Equatable {
     let value: T
@@ -883,24 +905,24 @@
         // Nested Unkeyed Container
         do {
             // Nested container for key should have a new key pushed on.
-            var secondLevelContainer = firstLevelContainer.nestedUnkeyedContainer(forKey: .a)
+            var secondLevelContainer = firstLevelContainer.nestedUnkeyedContainer(forKey: .b)
             expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.")
             expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.")
-            expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "New second-level keyed container had unexpected codingPath.")
+            expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "New second-level keyed container had unexpected codingPath.")
 
             // Appending a keyed container should not change existing coding paths.
             let thirdLevelContainerKeyed = secondLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self)
             expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.")
             expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.")
-            expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "Second-level unkeyed container's codingPath changed.")
-            expectEqualPaths(thirdLevelContainerKeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.a, nil], "New third-level keyed container had unexpected codingPath.")
+            expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "Second-level unkeyed container's codingPath changed.")
+            expectEqualPaths(thirdLevelContainerKeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.b, _TestKey(index: 0)], "New third-level keyed container had unexpected codingPath.")
             
             // Appending an unkeyed container should not change existing coding paths.
             let thirdLevelContainerUnkeyed = secondLevelContainer.nestedUnkeyedContainer()
             expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.")
             expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.")
-            expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "Second-level unkeyed container's codingPath changed.")
-            expectEqualPaths(thirdLevelContainerUnkeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.a, nil], "New third-level unkeyed container had unexpected codingPath.")
+            expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "Second-level unkeyed container's codingPath changed.")
+            expectEqualPaths(thirdLevelContainerUnkeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.b, _TestKey(index: 1)], "New third-level unkeyed container had unexpected codingPath.")
         }
     }
 }
diff --git a/TestFoundation/TestNSCharacterSet.swift b/TestFoundation/TestNSCharacterSet.swift
index 9371f59..c56da0d 100644
--- a/TestFoundation/TestNSCharacterSet.swift
+++ b/TestFoundation/TestNSCharacterSet.swift
@@ -1,4 +1,4 @@
-  // This source file is part of the Swift.org open source project
+// This source file is part of the Swift.org open source project
 //
 // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
@@ -7,8 +7,6 @@
 // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 
-
-
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
 import Foundation
 import XCTest
@@ -17,7 +15,47 @@
 import SwiftXCTest
 #endif
 
+private struct Box: Equatable {
+    private let ns: NSCharacterSet
+    private let swift: CharacterSet
+    
+    private init(ns: NSCharacterSet, swift: CharacterSet) {
+        self.ns = ns
+        self.swift = swift
+    }
+    
+    init(charactersIn string: String) {
+        self.ns = NSCharacterSet(charactersIn: string)
+        self.swift = CharacterSet(charactersIn: string)
+    }
+    
+    static var alphanumerics: Box {
+        return Box(ns: NSCharacterSet.alphanumerics._bridgeToObjectiveC(),
+                   swift: CharacterSet.alphanumerics)
+    }
+    
+    static var decimalDigits: Box {
+        return Box(ns: NSCharacterSet.decimalDigits._bridgeToObjectiveC(),
+                   swift: CharacterSet.decimalDigits)
+    }
 
+    // MARK: Equatable
+
+    static func ==(lhs: Box, rhs: Box) -> Bool {
+        return lhs.ns == rhs.ns
+            && lhs.swift == rhs.swift
+            && lhs.ns._bridgeToSwift() == rhs.ns._bridgeToSwift()
+            && lhs.swift._bridgeToObjectiveC() == rhs.swift._bridgeToObjectiveC()
+            && lhs.ns.isEqual(rhs.ns)
+            && lhs.ns.isEqual(rhs.swift)
+            && lhs.ns.isEqual(rhs.ns._bridgeToSwift())
+            && lhs.ns.isEqual(rhs.swift._bridgeToObjectiveC())
+            && lhs.swift._bridgeToObjectiveC().isEqual(rhs.ns)
+            && lhs.swift._bridgeToObjectiveC().isEqual(rhs.swift)
+            && lhs.swift._bridgeToObjectiveC().isEqual(rhs.ns._bridgeToSwift())
+            && lhs.swift._bridgeToObjectiveC().isEqual(rhs.swift._bridgeToObjectiveC())
+    }
+}
 
 class TestNSCharacterSet : XCTestCase {
     
@@ -36,6 +74,7 @@
             ("test_AnnexPlanes", test_AnnexPlanes),
             ("test_Planes", test_Planes),
             ("test_InlineBuffer", test_InlineBuffer),
+            ("test_Equatable", test_Equatable),
             // The following tests must remain disabled until SR-2509 is resolved.
             // ("test_Subtracting", test_Subtracting),
             // ("test_SubtractEmptySet", test_SubtractEmptySet),
@@ -282,5 +321,36 @@
         let expected = CharacterSet(charactersIn: "abc")
         XCTAssertEqual(expected, symmetricDifference)
     }
-}
+    
+    func test_Equatable() {
+        let equalPairs = [
+            ("", ""),
+            ("a", "a"),
+            ("abcde", "abcde"),
+            ("12345", "12345")
+        ]
+        
+        /*
+         Tests disabled due to CoreFoundation bug?
+         These NSCharacterSet pairs are (wrongly?) evaluated to be equal. Same behaviour can be observed on macOS 10.12.
+         Interestingly, on iOS 11 Simulator, they are evaluted to be _not_ equal,
+         while on iOS 10.3.1 Simulator, they are evaluted to be equal.
+         */
+        let notEqualPairs = [
+            ("abc", "123"),
+//            ("ab", "abc"),
+//            ("abc", "")
+        ]
+        
+        for pair in equalPairs {
+            XCTAssertEqual(Box(charactersIn: pair.0), Box(charactersIn: pair.1))
+        }
+        XCTAssertEqual(Box.alphanumerics, Box.alphanumerics)
+        
+        for pair in notEqualPairs {
+            XCTAssertNotEqual(Box(charactersIn: pair.0), Box(charactersIn: pair.1))
+        }
+        XCTAssertNotEqual(Box.alphanumerics, Box.decimalDigits)
+    }
 
+}
diff --git a/TestFoundation/TestNSDecimal.swift b/TestFoundation/TestNSDecimal.swift
index 6599281..9cacc4e 100644
--- a/TestFoundation/TestNSDecimal.swift
+++ b/TestFoundation/TestNSDecimal.swift
@@ -185,7 +185,7 @@
             _length: 0xff,
             _isNegative: 3,
             _isCompact: 4,
-            _reserved: UInt32(1<<18 + 1<<17 + 1),
+            _reserved: 1<<18 + 1<<17 + 1,
             _mantissa: (6, 7, 8, 9, 10, 11, 12, 13)
         )
         XCTAssertEqual(0x7f, explicit._exponent)
diff --git a/TestFoundation/TestNSError.swift b/TestFoundation/TestNSError.swift
index 43c9a47..8960aa6 100644
--- a/TestFoundation/TestNSError.swift
+++ b/TestFoundation/TestNSError.swift
@@ -16,6 +16,8 @@
     import SwiftXCTest
 #endif
 
+struct SwiftCustomNSError: Error, CustomNSError {
+}
 
 class TestNSError : XCTestCase {
     
@@ -23,6 +25,11 @@
         return [
             ("test_LocalizedError_errorDescription", test_LocalizedError_errorDescription),
             ("test_NSErrorAsError_localizedDescription", test_NSErrorAsError_localizedDescription),
+            ("test_CustomNSError_domain", test_CustomNSError_domain),
+            ("test_CustomNSError_userInfo", test_CustomNSError_userInfo),
+            ("test_CustomNSError_errorCode", test_CustomNSError_errorCode),
+            ("test_CustomNSError_errorCodeRawInt", test_CustomNSError_errorCodeRawInt),
+            ("test_CustomNSError_errorCodeRawUInt", test_CustomNSError_errorCodeRawUInt),
         ]
     }
     
@@ -40,4 +47,45 @@
         let error = nsError as Error
         XCTAssertEqual(error.localizedDescription, "Localized!")
     }
+
+    func test_CustomNSError_domain() {
+        XCTAssertEqual(SwiftCustomNSError.errorDomain, "TestFoundation.SwiftCustomNSError")
+    }
+
+    func test_CustomNSError_userInfo() {
+        let userInfo = SwiftCustomNSError().errorUserInfo
+        XCTAssertTrue(userInfo.isEmpty)
+    }
+
+    func test_CustomNSError_errorCode() {
+        enum SwiftError : Error, CustomNSError {
+            case zero
+            case one
+            case two
+        }
+
+        XCTAssertEqual(SwiftCustomNSError().errorCode, 1)
+
+        XCTAssertEqual(SwiftError.zero.errorCode, 0)
+        XCTAssertEqual(SwiftError.one.errorCode,  1)
+        XCTAssertEqual(SwiftError.two.errorCode,  2)
+    }
+
+    func test_CustomNSError_errorCodeRawInt() {
+        enum SwiftError : Int, Error, CustomNSError {
+            case minusOne  = -1
+            case fortyTwo = 42
+        }
+
+        XCTAssertEqual(SwiftError.minusOne.errorCode,  -1)
+        XCTAssertEqual(SwiftError.fortyTwo.errorCode, 42)
+    }
+
+    func test_CustomNSError_errorCodeRawUInt() {
+        enum SwiftError : UInt, Error, CustomNSError {
+            case fortyTwo = 42
+        }
+
+        XCTAssertEqual(SwiftError.fortyTwo.errorCode, 42)
+    }
 }
diff --git a/TestFoundation/TestNSGeometry.swift b/TestFoundation/TestNSGeometry.swift
index edd9d37..9367431 100644
--- a/TestFoundation/TestNSGeometry.swift
+++ b/TestFoundation/TestNSGeometry.swift
@@ -27,8 +27,12 @@
             ("test_CGFloat_LessThanOrEqual", test_CGFloat_LessThanOrEqual),
             ("test_CGFloat_GreaterThanOrEqual", test_CGFloat_GreaterThanOrEqual),
             ("test_CGPoint_BasicConstruction", test_CGPoint_BasicConstruction),
+            ("test_CGPoint_ExtendedConstruction", test_CGPoint_ExtendedConstruction),
             ("test_CGSize_BasicConstruction", test_CGSize_BasicConstruction),
+            ("test_CGSize_ExtendedConstruction", test_CGSize_ExtendedConstruction),
             ("test_CGRect_BasicConstruction", test_CGRect_BasicConstruction),
+            ("test_CGRect_ExtendedConstruction", test_CGRect_ExtendedConstruction),
+            ("test_CGRect_SpecialValues", test_CGRect_SpecialValues),
             ("test_NSEdgeInsets_BasicConstruction", test_NSEdgeInsets_BasicConstruction),
             ("test_NSEdgeInsetsEqual", test_NSEdgeInsetsEqual),
             ("test_NSMakePoint", test_NSMakePoint),
@@ -112,6 +116,20 @@
         XCTAssertEqual(p2.x, CGFloat(3.6))
         XCTAssertEqual(p2.y, CGFloat(4.5))
     }
+    
+    func test_CGPoint_ExtendedConstruction() {
+        let p1 = CGPoint.zero
+        XCTAssertEqual(p1.x, CGFloat(0))
+        XCTAssertEqual(p1.y, CGFloat(0))
+        
+        let p2 = CGPoint(x: Int(3), y: Int(4))
+        XCTAssertEqual(p2.x, CGFloat(3))
+        XCTAssertEqual(p2.y, CGFloat(4))
+        
+        let p3 = CGPoint(x: Double(3.6), y: Double(4.5))
+        XCTAssertEqual(p3.x, CGFloat(3.6))
+        XCTAssertEqual(p3.y, CGFloat(4.5))
+    }
 
     func test_CGSize_BasicConstruction() {
         let s1 = CGSize()
@@ -122,6 +140,20 @@
         XCTAssertEqual(s2.width, CGFloat(3.6))
         XCTAssertEqual(s2.height, CGFloat(4.5))
     }
+    
+    func test_CGSize_ExtendedConstruction() {
+        let s1 = CGSize.zero
+        XCTAssertEqual(s1.width, CGFloat(0))
+        XCTAssertEqual(s1.height, CGFloat(0))
+        
+        let s2 = CGSize(width: Int(3), height: Int(4))
+        XCTAssertEqual(s2.width, CGFloat(3))
+        XCTAssertEqual(s2.height, CGFloat(4))
+        
+        let s3 = CGSize(width: Double(3.6), height: Double(4.5))
+        XCTAssertEqual(s3.width, CGFloat(3.6))
+        XCTAssertEqual(s3.height, CGFloat(4.5))
+    }
 
     func test_CGRect_BasicConstruction() {
         let r1 = CGRect()
@@ -138,6 +170,46 @@
         XCTAssertEqual(r2.size.width, s.width)
         XCTAssertEqual(r2.size.height, s.height)
     }
+    
+    func test_CGRect_ExtendedConstruction() {
+        let r1 = CGRect.zero
+        XCTAssertEqual(r1.origin.x, CGFloat(0.0))
+        XCTAssertEqual(r1.origin.y, CGFloat(0.0))
+        XCTAssertEqual(r1.size.width, CGFloat(0.0))
+        XCTAssertEqual(r1.size.height, CGFloat(0.0))
+        
+        let r2 = CGRect(x: CGFloat(1.2), y: CGFloat(2.3), width: CGFloat(3.4), height: CGFloat(4.5))
+        XCTAssertEqual(r2.origin.x, CGFloat(1.2))
+        XCTAssertEqual(r2.origin.y, CGFloat(2.3))
+        XCTAssertEqual(r2.size.width, CGFloat(3.4))
+        XCTAssertEqual(r2.size.height, CGFloat(4.5))
+        
+        let r3 = CGRect(x: Double(1.2), y: Double(2.3), width: Double(3.4), height: Double(4.5))
+        XCTAssertEqual(r3.origin.x, CGFloat(1.2))
+        XCTAssertEqual(r3.origin.y, CGFloat(2.3))
+        XCTAssertEqual(r3.size.width, CGFloat(3.4))
+        XCTAssertEqual(r3.size.height, CGFloat(4.5))
+        
+        let r4 = CGRect(x: Int(1), y: Int(2), width: Int(3), height: Int(4))
+        XCTAssertEqual(r4.origin.x, CGFloat(1))
+        XCTAssertEqual(r4.origin.y, CGFloat(2))
+        XCTAssertEqual(r4.size.width, CGFloat(3))
+        XCTAssertEqual(r4.size.height, CGFloat(4))
+    }
+    
+    func test_CGRect_SpecialValues() {
+        let r1 = CGRect.null
+        XCTAssertEqual(r1.origin.x, CGFloat.infinity)
+        XCTAssertEqual(r1.origin.y, CGFloat.infinity)
+        XCTAssertEqual(r1.size.width, CGFloat(0.0))
+        XCTAssertEqual(r1.size.height, CGFloat(0.0))
+        
+        let r2 = CGRect.infinite
+        XCTAssertEqual(r2.origin.x, -CGFloat.greatestFiniteMagnitude / 2)
+        XCTAssertEqual(r2.origin.y, -CGFloat.greatestFiniteMagnitude / 2)
+        XCTAssertEqual(r2.size.width, CGFloat.greatestFiniteMagnitude)
+        XCTAssertEqual(r2.size.height, CGFloat.greatestFiniteMagnitude)
+    }
 
     func test_NSEdgeInsets_BasicConstruction() {
         let i1 = NSEdgeInsets()
diff --git a/TestFoundation/TestNSIndexPath.swift b/TestFoundation/TestNSIndexPath.swift
index 018875d..e260cdc 100644
--- a/TestFoundation/TestNSIndexPath.swift
+++ b/TestFoundation/TestNSIndexPath.swift
@@ -277,8 +277,10 @@
         let ip2: IndexPath = [1, 1, 1]
         
         XCTAssertNotEqual(ip1.hashValue, ip2.hashValue)
-        
-        IndexPath(indexes: [Int.max >> 8, 2, Int.max >> 36]).hashValue // this should not cause an overflow crash
+
+        // this should not cause an overflow crash
+        let hash: Int? = IndexPath(indexes: [Int.max >> 8, 2, Int.max >> 36]).hashValue
+        XCTAssertNotNil(hash)
     }
     
     func testEquality() {
diff --git a/TestFoundation/TestNSJSONSerialization.swift b/TestFoundation/TestNSJSONSerialization.swift
index 38dfe10..961026e 100644
--- a/TestFoundation/TestNSJSONSerialization.swift
+++ b/TestFoundation/TestNSJSONSerialization.swift
@@ -945,11 +945,12 @@
             ("test_booleanJSONObject", test_booleanJSONObject),
             ("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
             ("test_serializeDecimalNumberJSONObject", test_serializeDecimalNumberJSONObject),
+            ("test_serializeSortedKeys", test_serializeSortedKeys),
         ]
     }
 
-    func trySerialize(_ obj: Any) throws -> String {
-        let data = try JSONSerialization.data(withJSONObject: obj, options: [])
+    func trySerialize(_ obj: Any, options: JSONSerialization.WritingOptions = []) throws -> String {
+        let data = try JSONSerialization.data(withJSONObject: obj, options: options)
         guard let string = String(data: data, encoding: .utf8) else {
             XCTFail("Unable to create string")
             return ""
@@ -1334,6 +1335,19 @@
         } catch {
             XCTFail("Failed during serialization")
         }
+    } 
+    
+    func test_serializeSortedKeys() {
+        var dict: [String: Any]
+
+        dict = ["z": 1, "y": 1, "x": 1, "w": 1, "v": 1, "u": 1, "t": 1, "s": 1, "r": 1, "q": 1, ]
+        XCTAssertEqual(try trySerialize(dict, options: .sortedKeys), "{\"q\":1,\"r\":1,\"s\":1,\"t\":1,\"u\":1,\"v\":1,\"w\":1,\"x\":1,\"y\":1,\"z\":1}")
+
+        dict = ["aaaa": 1, "aaa": 1, "aa": 1, "a": 1]
+        XCTAssertEqual(try trySerialize(dict, options: .sortedKeys), "{\"a\":1,\"aa\":1,\"aaa\":1,\"aaaa\":1}")
+
+        dict = ["c": ["c":1,"b":1,"a":1],"b":["c":1,"b":1,"a":1],"a":["c":1,"b":1,"a":1]]
+        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}}")
     }
 
     fileprivate func createTestFile(_ path: String,_contents: Data) -> String? {
diff --git a/TestFoundation/TestNSNotificationCenter.swift b/TestFoundation/TestNSNotificationCenter.swift
index 0e75761..cea4b47 100644
--- a/TestFoundation/TestNSNotificationCenter.swift
+++ b/TestFoundation/TestNSNotificationCenter.swift
@@ -26,6 +26,10 @@
             ("test_postMultipleNotifications", test_postMultipleNotifications),
             ("test_addObserverForNilName", test_addObserverForNilName),
             ("test_removeObserver", test_removeObserver),
+            ("test_observeOnPostingQueue", test_observeOnPostingQueue),
+            ("test_observeOnSpecificQueuePostFromMainQueue", test_observeOnSpecificQueuePostFromMainQueue),
+            ("test_observeOnSpecificQueuePostFromObservedQueue", test_observeOnSpecificQueuePostFromObservedQueue),
+            ("test_observeOnSpecificQueuePostFromUnrelatedQueue", test_observeOnSpecificQueuePostFromUnrelatedQueue),
         ]
     }
     
@@ -149,5 +153,104 @@
         notificationCenter.post(name: notificationName, object: nil)
         XCTAssertTrue(flag)
     }
-
+    
+    func test_observeOnPostingQueue() {
+        let notificationCenter = NotificationCenter()
+        let name = Notification.Name(rawValue: "\(#function)_name")
+        let postingQueue = OperationQueue()
+        let expectation = self.expectation(description: "Observer was not notified.")
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: nil) { _ in
+            XCTAssertEqual(OperationQueue.current, postingQueue)
+            expectation.fulfill()
+        }
+        
+        postingQueue.addOperation {
+            notificationCenter.post(name: name, object: nil)
+        }
+        
+        self.waitForExpectations(timeout: 1)
+    }
+    
+    func test_observeOnSpecificQueuePostFromMainQueue() {
+        let name = Notification.Name(rawValue: "\(#function)_name")
+        let notificationCenter = NotificationCenter()
+        let operationQueue = OperationQueue()
+        var flag1 = false
+        var flag2 = false
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: operationQueue) { _ in
+            XCTAssertEqual(OperationQueue.current, operationQueue)
+            flag1 = true
+        }
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: .main) { _ in
+            XCTAssertEqual(OperationQueue.current, .main)
+            flag2 = true
+        }
+        
+        notificationCenter.post(name: name, object: nil)
+        // All observers should be notified synchronously regardless of the observer queue.
+        XCTAssertTrue(flag1)
+        XCTAssertTrue(flag2)
+    }
+    
+    func test_observeOnSpecificQueuePostFromObservedQueue() {
+        let name = Notification.Name(rawValue: "\(#function)_name")
+        let notificationCenter = NotificationCenter()
+        let observingQueue = OperationQueue()
+        let expectation = self.expectation(description: "Notification posting operation was not executed.")
+        var flag1 = false
+        var flag2 = false
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: observingQueue) { _ in
+            XCTAssertEqual(OperationQueue.current, observingQueue)
+            flag1 = true
+        }
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: .main) { _ in
+            XCTAssertEqual(OperationQueue.current, .main)
+            flag2 = true
+        }
+        
+        observingQueue.addOperation {
+            notificationCenter.post(name: name, object: nil)
+            // All observers should be notified synchronously regardless of the observer queue.
+            XCTAssertTrue(flag1)
+            XCTAssertTrue(flag2)
+            expectation.fulfill()
+        }
+        
+        self.waitForExpectations(timeout: 1)
+    }
+    
+    func test_observeOnSpecificQueuePostFromUnrelatedQueue() {
+        let name = Notification.Name(rawValue: "\(#function)_name")
+        let notificationCenter = NotificationCenter()
+        let operationQueue = OperationQueue()
+        let postingQueue = OperationQueue()
+        let expectation = self.expectation(description: "Notification posting operation was not executed.")
+        var flag1 = false
+        var flag2 = false
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: operationQueue) { _ in
+            XCTAssertEqual(OperationQueue.current, operationQueue)
+            flag1 = true
+        }
+        
+        _ = notificationCenter.addObserver(forName: name, object: nil, queue: .main) { _ in
+            XCTAssertEqual(OperationQueue.current, .main)
+            flag2 = true
+        }
+        
+        postingQueue.addOperation {
+            notificationCenter.post(name: name, object: nil)
+            // All observers should be notified synchronously regardless of the observer queue.
+            XCTAssertTrue(flag1)
+            XCTAssertTrue(flag2)
+            expectation.fulfill()
+        }
+        
+        self.waitForExpectations(timeout: 1)
+    }
 }
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index 62e16c9..d3ddde8 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -21,6 +21,7 @@
     static var allTests: [(String, (TestNSNumber) -> () throws -> Void)] {
         return [
             ("test_NumberWithBool", test_NumberWithBool ),
+            ("test_CFBoolean", test_CFBoolean ),
             ("test_numberWithChar", test_numberWithChar ),
             ("test_numberWithUnsignedChar", test_numberWithUnsignedChar ),
             ("test_numberWithShort", test_numberWithShort ),
@@ -41,6 +42,7 @@
             ("test_compareNumberWithDouble", test_compareNumberWithDouble ),
             ("test_description", test_description ),
             ("test_descriptionWithLocale", test_descriptionWithLocale ),
+            ("test_objCType", test_objCType ),
         ]
     }
     
@@ -977,4 +979,44 @@
             XCTAssertEqual(receivedDesc, expectedDesc, "expected \(expectedDesc) but received \(receivedDesc)")
         }
     }
+
+    func test_objCType() {
+        let objCType: (NSNumber) -> UnicodeScalar = { number in
+            return UnicodeScalar(UInt8(number.objCType.pointee))
+        }
+
+        XCTAssertEqual("c" /* 0x63 */, objCType(NSNumber(value: true)))
+
+        XCTAssertEqual("c" /* 0x63 */, objCType(NSNumber(value: Int8.max)))
+        XCTAssertEqual("s" /* 0x73 */, objCType(NSNumber(value: UInt8(Int8.max))))
+        XCTAssertEqual("s" /* 0x73 */, objCType(NSNumber(value: UInt8(Int8.max) + 1)))
+
+        XCTAssertEqual("s" /* 0x73 */, objCType(NSNumber(value: Int16.max)))
+        XCTAssertEqual("i" /* 0x69 */, objCType(NSNumber(value: UInt16(Int16.max))))
+        XCTAssertEqual("i" /* 0x69 */, objCType(NSNumber(value: UInt16(Int16.max) + 1)))
+
+        XCTAssertEqual("i" /* 0x69 */, objCType(NSNumber(value: Int32.max)))
+        XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: UInt32(Int32.max))))
+        XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: UInt32(Int32.max) + 1)))
+
+        XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: Int64.max)))
+        // When value is lower equal to `Int64.max`, it returns 'q' even if using `UInt64`
+        XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: UInt64(Int64.max))))
+        XCTAssertEqual("Q" /* 0x51 */, objCType(NSNumber(value: UInt64(Int64.max) + 1)))
+
+        // Depends on architectures
+        #if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+            XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: Int.max)))
+            // When value is lower equal to `Int.max`, it returns 'q' even if using `UInt`
+            XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: UInt(Int.max))))
+            XCTAssertEqual("Q" /* 0x51 */, objCType(NSNumber(value: UInt(Int.max) + 1)))
+        #elseif arch(i386) || arch(arm)
+            XCTAssertEqual("i" /* 0x71 */, objCType(NSNumber(value: Int.max)))
+            XCTAssertEqual("q" /* 0x71 */, objCType(NSNumber(value: UInt(Int.max))))
+            XCTAssertEqual("q" /* 0x51 */, objCType(NSNumber(value: UInt(Int.max) + 1)))
+        #endif
+
+        XCTAssertEqual("f" /* 0x66 */, objCType(NSNumber(value: Float.greatestFiniteMagnitude)))
+        XCTAssertEqual("d" /* 0x64 */, objCType(NSNumber(value: Double.greatestFiniteMagnitude)))
+    }
 }
diff --git a/TestFoundation/TestNSOperationQueue.swift b/TestFoundation/TestNSOperationQueue.swift
index 783115f..57d7835 100644
--- a/TestFoundation/TestNSOperationQueue.swift
+++ b/TestFoundation/TestNSOperationQueue.swift
@@ -23,7 +23,13 @@
         return [
             ("test_OperationPriorities", test_OperationPriorities),
             ("test_OperationCount", test_OperationCount),
-            ("test_AsyncOperation", test_AsyncOperation)
+            ("test_AsyncOperation", test_AsyncOperation),
+            ("test_isExecutingWorks", test_isExecutingWorks),
+            ("test_MainQueueGetter", test_MainQueueGetter),
+            ("test_CurrentQueueOnMainQueue", test_CurrentQueueOnMainQueue),
+            ("test_CurrentQueueOnBackgroundQueue", test_CurrentQueueOnBackgroundQueue),
+            ("test_CurrentQueueWithCustomUnderlyingQueue", test_CurrentQueueWithCustomUnderlyingQueue),
+            ("test_CurrentQueueWithUnderlyingQueueResetToNil", test_CurrentQueueWithUnderlyingQueueResetToNil),
         ]
     }
     
@@ -68,6 +74,26 @@
         XCTAssertEqual(msgOperations[3], "Operation4 executed")
     }
 
+    func test_isExecutingWorks() {
+        class _OperationBox {
+            var operation: Operation?
+            init() {
+                self.operation = nil
+            }
+        }
+        let queue = OperationQueue()
+        let opBox = _OperationBox()
+        let op = BlockOperation(block: { XCTAssertEqual(true, opBox.operation?.isExecuting) })
+        opBox.operation = op
+        XCTAssertFalse(op.isExecuting)
+
+        queue.addOperation(op)
+        queue.waitUntilAllOperationsAreFinished()
+        XCTAssertFalse(op.isExecuting)
+
+        opBox.operation = nil /* break the reference cycle op -> <closure> -> opBox -> op */
+    }
+
     func test_AsyncOperation() {
         let operation = AsyncOperation()
         XCTAssertFalse(operation.isExecuting)
@@ -82,6 +108,61 @@
         XCTAssertFalse(operation.isExecuting)
         XCTAssertTrue(operation.isFinished)
     }
+    
+    func test_MainQueueGetter() {
+        XCTAssertTrue(OperationQueue.main === OperationQueue.main)
+        
+        /*
+         This call is only to check if OperationQueue.main returns a living instance.
+         There used to be a bug where subsequent OperationQueue.main call would return a "dangling pointer".
+         */
+        XCTAssertFalse(OperationQueue.main.isSuspended)
+    }
+    
+    func test_CurrentQueueOnMainQueue() {
+        XCTAssertTrue(OperationQueue.main === OperationQueue.current)
+    }
+    
+    func test_CurrentQueueOnBackgroundQueue() {
+        let expectation = self.expectation(description: "Background execution")
+        
+        let operationQueue = OperationQueue()
+        operationQueue.addOperation {
+            XCTAssertEqual(operationQueue, OperationQueue.current)
+            expectation.fulfill()
+        }
+        
+        waitForExpectations(timeout: 1)
+    }
+    
+    func test_CurrentQueueWithCustomUnderlyingQueue() {
+        let expectation = self.expectation(description: "Background execution")
+        
+        let operationQueue = OperationQueue()
+        operationQueue.underlyingQueue = DispatchQueue(label: "underlying_queue")
+        
+        operationQueue.addOperation {
+            XCTAssertEqual(operationQueue, OperationQueue.current)
+            expectation.fulfill()
+        }
+        
+        waitForExpectations(timeout: 1)
+    }
+    
+    func test_CurrentQueueWithUnderlyingQueueResetToNil() {
+        let expectation = self.expectation(description: "Background execution")
+        
+        let operationQueue = OperationQueue()
+        operationQueue.underlyingQueue = DispatchQueue(label: "underlying_queue")
+        operationQueue.underlyingQueue = nil
+        
+        operationQueue.addOperation {
+            XCTAssertEqual(operationQueue, OperationQueue.current)
+            expectation.fulfill()
+        }
+        
+        waitForExpectations(timeout: 1)
+    }
 }
 
 class AsyncOperation: Operation {
diff --git a/TestFoundation/TestNSPersonNameComponents.swift b/TestFoundation/TestNSPersonNameComponents.swift
index 78e75df..4f0bd45 100644
--- a/TestFoundation/TestNSPersonNameComponents.swift
+++ b/TestFoundation/TestNSPersonNameComponents.swift
@@ -17,13 +17,42 @@
     import SwiftXCTest
 #endif
 
+private func assertEqual(_ lhs:PersonNameComponents,
+                         _ rhs: PersonNameComponents,
+                         file: StaticString = #file,
+                         line: UInt = #line) {
+    assert(equal: true, lhs, rhs, file: file, line: line)
+}
 
+private func assertNotEqual(_ lhs:PersonNameComponents,
+                            _ rhs: PersonNameComponents,
+                            file: StaticString = #file,
+                            line: UInt = #line) {
+    assert(equal: false, lhs, rhs, file: file, line: line)
+}
+
+private func assert(equal: Bool,
+                    _ lhs:PersonNameComponents,
+                    _ rhs: PersonNameComponents,
+                    file: StaticString = #file,
+                    line: UInt = #line) {
+    if equal {
+        XCTAssertEqual(lhs, rhs, file: file, line: line)
+        XCTAssertEqual(lhs._bridgeToObjectiveC(), rhs._bridgeToObjectiveC(), file: file, line: line)
+        XCTAssertTrue(lhs._bridgeToObjectiveC().isEqual(rhs), file: file, line: line)
+    } else {
+        XCTAssertNotEqual(lhs, rhs, file: file, line: line)
+        XCTAssertNotEqual(lhs._bridgeToObjectiveC(), rhs._bridgeToObjectiveC(), file: file, line: line)
+        XCTAssertFalse(lhs._bridgeToObjectiveC().isEqual(rhs), file: file, line: line)
+    }
+}
 
 class TestNSPersonNameComponents : XCTestCase {
     
     static var allTests: [(String, (TestNSPersonNameComponents) -> () throws -> Void)] {
         return [
             ("testCopy", testCopy),
+            ("testEquality", testEquality),
         ]
     }
     
@@ -39,6 +68,78 @@
         XCTAssertEqual(original.phoneticRepresentation!.givenName,copy.phoneticRepresentation!.givenName)
         XCTAssertNil(copy.phoneticRepresentation!.phoneticRepresentation)
     }
+
+    func testEquality() {
+        do {
+            let lhs = PersonNameComponents()
+            let rhs = PersonNameComponents()
+            assertEqual(lhs, rhs)
+        }
+
+        let lhs = self.makePersonNameComponentsWithTestValues()
+        do {
+            let rhs = self.makePersonNameComponentsWithTestValues()
+            assertEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.namePrefix = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.givenName = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.middleName = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.familyName = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.nameSuffix = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.nickname = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+        do {
+            var rhs = self.makePersonNameComponentsWithTestValues()
+            rhs.phoneticRepresentation?.namePrefix = "differentValue"
+            assertNotEqual(lhs, rhs)
+        }
+    }
+
+    // MARK: - Helpers
+
+    private func makePersonNameComponentsWithTestValues() -> PersonNameComponents {
+        var components = PersonNameComponents()
+        components.namePrefix = "namePrefix"
+        components.givenName = "givenName"
+        components.middleName = "middleName"
+        components.familyName = "familyName"
+        components.nameSuffix = "nameSuffix"
+        components.nickname = "nickname"
+        components.phoneticRepresentation = {
+            var components = PersonNameComponents()
+            components.namePrefix = "phonetic_namePrefix"
+            components.givenName = "phonetic_givenName"
+            components.middleName = "phonetic_middleName"
+            components.familyName = "phonetic_familyName"
+            components.nameSuffix = "phonetic_nameSuffix"
+            components.nickname = "phonetic_nickname"
+            return components
+        }()
+        return components
+    }
 }
 
         
diff --git a/TestFoundation/TestNSPredicate.swift b/TestFoundation/TestNSPredicate.swift
index 641d605..4e88e33 100644
--- a/TestFoundation/TestNSPredicate.swift
+++ b/TestFoundation/TestNSPredicate.swift
@@ -101,6 +101,9 @@
         let predicateA = NSPredicate(value: true)
         let predicateB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: predicateA)) as! NSPredicate
         XCTAssertEqual(predicateA, predicateB, "Archived then unarchived uuid must be equal.")
+        let predicateC = NSPredicate(value: false)
+        let predicateD = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: predicateC)) as! NSPredicate
+        XCTAssertEqual(predicateC, predicateD, "Archived then unarchived uuid must be equal.")
     }
     
     func test_copy() {
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 58a1c8a..85dac2a 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -1134,6 +1134,10 @@
 
         let s5 = NSString(string: "\r\ncats😺")
         XCTAssertEqual(s5.substring(with: NSMakeRange(1,6)), "\ncats�")
+
+        // SR-3363
+        let s6 = NSString(string: "Beyonce\u{301} and Tay")
+        XCTAssertEqual(s6.substring(with: NSMakeRange(7, 9)), "\u{301} and Tay")
     }
 }
 
diff --git a/TestFoundation/TestNSURLProtocol.swift b/TestFoundation/TestNSURLProtocol.swift
new file mode 100644
index 0000000..4a49798
--- /dev/null
+++ b/TestFoundation/TestNSURLProtocol.swift
@@ -0,0 +1,165 @@
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
+import Foundation
+import XCTest
+#else
+import SwiftFoundation
+import SwiftXCTest
+#endif
+
+class TestNSURLProtocol : LoopbackServerTest {
+    
+    static var allTests: [(String, (TestNSURLProtocol) -> () throws -> Void)] {
+        return [
+            ("test_interceptResponse", test_interceptResponse),
+            ("test_interceptRequest", test_interceptRequest),
+            ("test_multipleCustomProtocols", test_multipleCustomProtocols),
+            ("test_customProtocolResponseWithDelegate", test_customProtocolResponseWithDelegate),
+            ("test_customProtocolSetDataInResponseWithDelegate", test_customProtocolSetDataInResponseWithDelegate),
+        ]
+    }
+    
+    func test_interceptResponse() {
+        let urlString = "http://127.0.0.1:\(TestNSURLProtocol.serverPort)/USA"
+        let url = URL(string: urlString)!
+        let config = URLSessionConfiguration.default
+        config.protocolClasses = [CustomProtocol.self]
+        config.timeoutIntervalForRequest = 8
+        let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+        let expect = expectation(description: "GET \(urlString): with a custom protocol")
+        let task = session.dataTask(with: url) { data, response, error in
+            defer { expect.fulfill() }
+            if let e = error as? URLError {
+                XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
+                return
+            }
+            let httpResponse = response as! HTTPURLResponse?
+            XCTAssertEqual(429, httpResponse!.statusCode, "HTTP response code is not 429")
+        }
+        task.resume()
+        waitForExpectations(timeout: 12)
+    }
+    
+    func test_interceptRequest() {
+        let urlString = "ssh://127.0.0.1:\(TestNSURLProtocol.serverPort)/USA"
+        let url = URL(string: urlString)!
+        let config = URLSessionConfiguration.default
+        config.protocolClasses = [InterceptableRequest.self]
+        config.timeoutIntervalForRequest = 8
+        let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+        let expect = expectation(description: "GET \(urlString): with a custom protocol")
+        let task = session.dataTask(with: url) { data, response, error in
+            defer { expect.fulfill() }
+            if let e = error as? URLError {
+                XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
+                return
+            }
+            let httpResponse = response as! HTTPURLResponse?
+            let responseURL = URL(string: "http://google.com")
+            XCTAssertEqual(responseURL, httpResponse?.url, "Unexpected url")
+            XCTAssertEqual(200, httpResponse!.statusCode, "HTTP response code is not 200")
+        }
+        task.resume()
+        waitForExpectations(timeout: 12)
+    }
+    
+    func test_multipleCustomProtocols() {
+        let urlString = "http://127.0.0.1:\(TestNSURLProtocol.serverPort)/Nepal"
+        let url = URL(string: urlString)!
+        let config = URLSessionConfiguration.default
+        config.protocolClasses = [InterceptableRequest.self, CustomProtocol.self]
+        let expect = expectation(description: "GET \(urlString): with a custom protocol")
+        let session = URLSession(configuration: config)
+        let task = session.dataTask(with: url) { data, response, error in
+            defer { expect.fulfill() }
+            if let e = error as? URLError {
+                XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
+                return
+            }
+            let httpResponse = response as! HTTPURLResponse
+            print(httpResponse.statusCode)
+            XCTAssertEqual(429, httpResponse.statusCode, "Status code is not 429")
+        }
+        task.resume()
+        waitForExpectations(timeout: 12)
+    }
+    
+    func test_customProtocolResponseWithDelegate() {
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
+        let url = URL(string: urlString)!
+        let d = DataTask(with: expectation(description: "GET \(urlString): with a custom protocol and delegate"), protocolClasses: [CustomProtocol.self])
+        d.responseReceivedExpectation = expectation(description: "GET \(urlString): response received")
+        d.run(with: url)
+        waitForExpectations(timeout: 12)
+    }
+    
+    func test_customProtocolSetDataInResponseWithDelegate() {
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
+        let url = URL(string: urlString)!
+        let d = DataTask(with: expectation(description: "GET \(urlString): with a custom protocol and delegate"), protocolClasses: [CustomProtocol.self])
+        d.run(with: url)
+        waitForExpectations(timeout: 12)
+        if !d.error {
+            XCTAssertEqual(d.capital, "Kathmandu", "test_dataTaskWithURLRequest returned an unexpected result")
+        }
+    }
+}
+
+class InterceptableRequest : URLProtocol {
+
+    override class func canInit(with request: URLRequest) -> Bool {
+        return request.url?.scheme == "ssh"
+    }
+    
+    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
+        return request
+    }
+    
+    override func startLoading() {
+        let urlString = "http://google.com"
+        let url = URL(string: urlString)!
+        let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: [:])
+        self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
+        self.client?.urlProtocolDidFinishLoading(self)
+        
+    }
+
+    override func stopLoading() {
+        return
+    }
+}
+
+class CustomProtocol : URLProtocol {
+    
+    override class func canInit(with request: URLRequest) -> Bool {
+        return true
+    }
+    
+    func sendResponse(statusCode: Int, headers: [String: String] = [:], data: Data) {
+        let response = HTTPURLResponse(url: self.request.url!, statusCode: statusCode, httpVersion: "HTTP/1.1", headerFields: headers)
+        let capital = "Kathmandu"
+        let data = capital.data(using: String.Encoding.utf8)
+        self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
+        self.client?.urlProtocol(self, didLoad: data!)
+        self.client?.urlProtocolDidFinishLoading(self)
+    }
+    
+    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
+        return request
+    }
+    
+    override func startLoading() {
+        sendResponse(statusCode: 429, data: Data())
+    }
+    
+    override func stopLoading() {
+        return
+    }
+}
diff --git a/TestFoundation/TestNSURLSession.swift b/TestFoundation/TestNSURLSession.swift
index 285ddd4..cf44ab6 100644
--- a/TestFoundation/TestNSURLSession.swift
+++ b/TestFoundation/TestNSURLSession.swift
@@ -15,9 +15,7 @@
     import SwiftXCTest
 #endif
 
-class TestURLSession : XCTestCase {
-    
-    static var serverPort: Int = -1
+class TestURLSession : LoopbackServerTest {
     
     static var allTests: [(String, (TestURLSession) -> () throws -> Void)] {
         return [
@@ -37,49 +35,21 @@
             ("test_verifyRequestHeaders", test_verifyRequestHeaders),
             ("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
             ("test_timeoutInterval", test_timeoutInterval),
-            ("test_customProtocol", test_customProtocol),
-	    ("test_customProtocolResponseWithDelegate", test_customProtocolResponseWithDelegate),
             ("test_httpRedirection", test_httpRedirection),
             ("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
+            ("test_http0_9SimpleResponses", test_http0_9SimpleResponses),
+            ("test_outOfRangeButCorrectlyFormattedHTTPCode", test_outOfRangeButCorrectlyFormattedHTTPCode),
+            ("test_missingContentLengthButStillABody", test_missingContentLengthButStillABody),
+            ("test_illegalHTTPServerResponses", test_illegalHTTPServerResponses),
+            ("test_dataTaskWithSharedDelegate", test_dataTaskWithSharedDelegate),
+            ("test_simpleUploadWithDelegate", test_simpleUploadWithDelegate),
         ]
     }
     
-    override class func setUp() {
-        super.setUp()
-        func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
-            let start = 21961
-            for port in start...(start+100) { //we must find at least one port to bind
-                do {
-                    serverPort = port
-                    let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
-                    try test.start(started: condition)
-                    try test.readAndRespond()
-                    test.stop()
-                } catch let e as ServerError {
-                    if e.operation == "bind" { continue }
-                    throw e
-                }
-            }
-        }
-        
-        let serverReady = ServerSemaphore()
-        globalDispatchQueue.async {
-            do {
-                try runServer(with: serverReady)
-                
-            } catch {
-                XCTAssertTrue(true)
-                return
-            }
-        }
-        
-        serverReady.wait()
-    }
-    
     func test_dataTaskWithURL() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
         let url = URL(string: urlString)!
-        let d = DataTask(with: expectation(description: "data task"))
+        let d = DataTask(with: expectation(description: "GET \(urlString): with a delegate"))
         d.run(with: url)
         waitForExpectations(timeout: 12)
         if !d.error {
@@ -93,7 +63,7 @@
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 8
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        let expect = expectation(description: "URL test with completion handler")
+        let expect = expectation(description: "GET \(urlString): with a completion handler")
         var expectedResult = "unknown"
         let task = session.dataTask(with: url) { data, response, error in
             defer { expect.fulfill() }
@@ -112,7 +82,7 @@
     func test_dataTaskWithURLRequest() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
         let urlRequest = URLRequest(url: URL(string: urlString)!)
-        let d = DataTask(with: expectation(description: "data task"))
+        let d = DataTask(with: expectation(description: "GET \(urlString): with a delegate"))
         d.run(with: urlRequest)
         waitForExpectations(timeout: 12)
         if !d.error {
@@ -126,7 +96,7 @@
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 8
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        let expect = expectation(description: "URL test with completion handler")
+        let expect = expectation(description: "GET \(urlString): with a completion handler")
         var expectedResult = "unknown"
         let task = session.dataTask(with: urlRequest) { data, response, error in
             defer { expect.fulfill() }
@@ -145,7 +115,7 @@
     func test_downloadTaskWithURL() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
         let url = URL(string: urlString)!
-        let d = DownloadTask(with: expectation(description: "download task with delegate"))
+        let d = DownloadTask(with: expectation(description: "Download GET \(urlString): with a delegate"))
         d.run(with: url)
         waitForExpectations(timeout: 12)
     }
@@ -153,7 +123,7 @@
     func test_downloadTaskWithURLRequest() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
         let urlRequest = URLRequest(url: URL(string: urlString)!)
-        let d = DownloadTask(with: expectation(description: "download task with delegate"))
+        let d = DownloadTask(with: expectation(description: "Download GET \(urlString): with a delegate"))
         d.run(with: urlRequest)
         waitForExpectations(timeout: 12)
     }
@@ -161,9 +131,10 @@
     func test_downloadTaskWithRequestAndHandler() {
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 8
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        let expect = expectation(description: "download task with handler")
-        let req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt")!)
+        let expect = expectation(description: "Download GET \(urlString): with a completion handler")
+        let req = URLRequest(url: URL(string: urlString)!)
         let task = session.downloadTask(with: req) { (_, _, error) -> Void in
             XCTAssertNil(error as? URLError, "error = \(error as! URLError)")
             expect.fulfill()
@@ -175,9 +146,10 @@
     func test_downloadTaskWithURLAndHandler() {
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 8
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        let expect = expectation(description: "download task with handler")
-        let req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt")!)
+        let expect = expectation(description: "Download GET \(urlString): with a completion handler")
+        let req = URLRequest(url: URL(string: urlString)!)
         let task = session.downloadTask(with: req) { (_, _, error) -> Void in
             if let e = error as? URLError {
                 XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
@@ -189,12 +161,13 @@
     }
     
     func test_finishTasksAndInvalidate() {
-        let invalidateExpectation = expectation(description: "URLSession wasn't invalidated")
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
+        let invalidateExpectation = expectation(description: "Session invalidation")
         let delegate = SessionDelegate(invalidateExpectation: invalidateExpectation)
-        let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal")!
+        let url = URL(string: urlString)!
         let session = URLSession(configuration: URLSessionConfiguration.default,
                                  delegate: delegate, delegateQueue: nil)
-        let completionExpectation = expectation(description: "dataTask completion block wasn't called")
+        let completionExpectation = expectation(description: "GET \(urlString): task completion before session invalidation")
         let task = session.dataTask(with: url) { (_, _, _) in
             completionExpectation.fulfill()
         }
@@ -204,11 +177,12 @@
     }
     
     func test_taskError() {
-        let url = URL(string: "http://127.0.0.1:-1/Nepal")!
+        let urlString = "http://127.0.0.1:-1/Nepal"
+        let url = URL(string: urlString)!
         let session = URLSession(configuration: URLSessionConfiguration.default,
                                  delegate: nil,
                                  delegateQueue: nil)
-        let completionExpectation = expectation(description: "dataTask completion block wasn't called")
+        let completionExpectation = expectation(description: "GET \(urlString): Bad URL error")
         let task = session.dataTask(with: url) { (_, _, result) in
             let error = result as? URLError
             XCTAssertNotNil(error)
@@ -237,9 +211,10 @@
     }
     
     func test_cancelTask() {
-        let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Peru")!
-        let d = DataTask(with: expectation(description: "Task to be canceled"))
-        d.cancelExpectation = expectation(description: "URLSessionTask wasn't canceled")
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
+        let url = URL(string: urlString)!
+        let d = DataTask(with: expectation(description: "GET \(urlString): task cancelation"))
+        d.cancelExpectation = expectation(description: "GET \(urlString): task canceled")
         d.run(with: url)
         d.cancel()
         waitForExpectations(timeout: 12)
@@ -248,9 +223,10 @@
     func test_verifyRequestHeaders() {
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 5
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/requestHeaders"
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        var expect = expectation(description: "download task with handler")
-        var req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/requestHeaders")!)
+        var expect = expectation(description: "POST \(urlString): get request headers")
+        var req = URLRequest(url: URL(string: urlString)!)
         let headers = ["header1": "value1"]
         req.httpMethod = "POST"
         req.allHTTPHeaderFields = headers
@@ -274,9 +250,10 @@
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 5
         config.httpAdditionalHeaders = ["header2": "svalue2", "header3": "svalue3"]
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/requestHeaders"
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        var expect = expectation(description: "download task with handler")
-        var req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/requestHeaders")!)
+        var expect = expectation(description: "POST \(urlString) with additional headers")
+        var req = URLRequest(url: URL(string: urlString)!)
         let headers = ["header1": "rvalue1", "header2": "rvalue2"]
         req.httpMethod = "POST"
         req.allHTTPHeaderFields = headers
@@ -297,9 +274,10 @@
     func test_taskTimeout() {
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 5
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        var expect = expectation(description: "download task with handler")
-        let req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Peru")!)
+        var expect = expectation(description: "GET \(urlString): no timeout")
+        let req = URLRequest(url: URL(string: urlString)!)
         var task = session.dataTask(with: req) { (data, _, error) -> Void in
             defer { expect.fulfill() }
             XCTAssertNil(error as? URLError, "error = \(error as! URLError)")
@@ -312,8 +290,9 @@
     func test_timeoutInterval() {
         let config = URLSessionConfiguration.default
         config.timeoutIntervalForRequest = 10
+        let urlString = "http://127.0.0.1:-1/Peru"
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        var expect = expectation(description: "download task with handler")
+        var expect = expectation(description: "GET \(urlString): will timeout")
         var req = URLRequest(url: URL(string: "http://127.0.0.1:-1/Peru")!)
         req.timeoutInterval = 1
         var task = session.dataTask(with: req) { (data, _, error) -> Void in
@@ -325,48 +304,20 @@
         waitForExpectations(timeout: 30)
     }
     
-    func test_customProtocol () {
-        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/USA"
-        let url = URL(string: urlString)!
-        let config = URLSessionConfiguration.default
-        config.protocolClasses = [CustomProtocol.self]
-        config.timeoutIntervalForRequest = 8
-        let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
-        let expect = expectation(description: "URL test with custom protocol")
-        let task = session.dataTask(with: url) { data, response, error in
-            defer { expect.fulfill() }
-            if let e = error as? URLError {
-                XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
-                return
-            }
-            let httpResponse = response as! HTTPURLResponse?
-            XCTAssertEqual(429, httpResponse!.statusCode, "HTTP response code is not 429")
-        }
-        task.resume()
-        waitForExpectations(timeout: 12)
-    }
-
-    func test_customProtocolResponseWithDelegate() {
-        let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Peru")!
-        let d = DataTask(with: expectation(description: "Custom protocol with delegate"), protocolClasses: [CustomProtocol.self])
-        d.responseReceivedExpectation = expectation(description: "A response wasn't received")
-        d.run(with: url)
-        waitForExpectations(timeout: 12)
-    }
-    
     func test_httpRedirection() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
         let url = URL(string: urlString)!
-        let d = HTTPRedirectionDataTask(with: expectation(description: "data task"))
+        let d = HTTPRedirectionDataTask(with: expectation(description: "GET \(urlString): with HTTP redirection"))
         d.run(with: url)
         waitForExpectations(timeout: 12)
     }
 
     func test_httpRedirectionTimeout() {
-        var req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates")!)
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
+        var req = URLRequest(url: URL(string: urlString)!)
         req.timeoutInterval = 3
         let config = URLSessionConfiguration.default
-        var expect = expectation(description: "download task with handler")
+        var expect = expectation(description: "GET \(urlString): timeout with redirection ")
         let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
         let task = session.dataTask(with: req) { data, response, error in
             defer { expect.fulfill() }
@@ -378,8 +329,154 @@
         task.resume()
         waitForExpectations(timeout: 12)
     }
+
+    func test_http0_9SimpleResponses() {
+        for brokenCity in ["Pompeii", "Sodom"] {
+            let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/LandOfTheLostCities/\(brokenCity)"
+            let url = URL(string: urlString)!
+
+            let config = URLSessionConfiguration.default
+            config.timeoutIntervalForRequest = 8
+            let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+            let expect = expectation(description: "GET \(urlString): simple HTTP/0.9 response")
+            var expectedResult = "unknown"
+            let task = session.dataTask(with: url) { data, response, error in
+                XCTAssertNotNil(data)
+                XCTAssertNotNil(response)
+                XCTAssertNil(error)
+
+                defer { expect.fulfill() }
+
+                guard let httpResponse = response as? HTTPURLResponse else {
+                    XCTFail("response (\(response.debugDescription)) invalid")
+                    return
+                }
+                XCTAssertEqual(200, httpResponse.statusCode, "HTTP response code is not 200")
+            }
+            task.resume()
+            waitForExpectations(timeout: 12)
+        }
+    }
+
+    func test_outOfRangeButCorrectlyFormattedHTTPCode() {
+        let brokenCity = "Kameiros"
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/LandOfTheLostCities/\(brokenCity)"
+        let url = URL(string: urlString)!
+
+        let config = URLSessionConfiguration.default
+        config.timeoutIntervalForRequest = 8
+        let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+        let expect = expectation(description: "GET \(urlString): out of range HTTP code")
+        let task = session.dataTask(with: url) { data, response, error in
+            XCTAssertNotNil(data)
+            XCTAssertNotNil(response)
+            XCTAssertNil(error)
+
+            defer { expect.fulfill() }
+
+            guard let httpResponse = response as? HTTPURLResponse else {
+                XCTFail("response (\(response.debugDescription)) invalid")
+                return
+            }
+            XCTAssertEqual(999, httpResponse.statusCode, "HTTP response code is not 999")
+        }
+        task.resume()
+        waitForExpectations(timeout: 12)
+    }
+
+    func test_missingContentLengthButStillABody() {
+        let brokenCity = "Myndus"
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/LandOfTheLostCities/\(brokenCity)"
+        let url = URL(string: urlString)!
+
+        let config = URLSessionConfiguration.default
+        config.timeoutIntervalForRequest = 8
+        let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+        let expect = expectation(description: "GET \(urlString): missing content length")
+        let task = session.dataTask(with: url) { data, response, error in
+            XCTAssertNotNil(data)
+            XCTAssertNotNil(response)
+            XCTAssertNil(error)
+
+            defer { expect.fulfill() }
+
+            guard let httpResponse = response as? HTTPURLResponse else {
+                XCTFail("response (\(response.debugDescription)) invalid")
+                return
+            }
+            XCTAssertEqual(200, httpResponse.statusCode, "HTTP response code is not 200")
+        }
+        task.resume()
+        waitForExpectations(timeout: 12)
+    }
+
+
+    func test_illegalHTTPServerResponses() {
+        for brokenCity in ["Gomorrah", "Dinavar", "Kuhikugu"] {
+            let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/LandOfTheLostCities/\(brokenCity)"
+            let url = URL(string: urlString)!
+
+            let config = URLSessionConfiguration.default
+            config.timeoutIntervalForRequest = 8
+            let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+            let expect = expectation(description: "GET \(urlString): illegal response")
+            let task = session.dataTask(with: url) { data, response, error in
+                XCTAssertNil(data)
+                XCTAssertNil(response)
+                XCTAssertNotNil(error)
+
+                defer { expect.fulfill() }
+            }
+            task.resume()
+            waitForExpectations(timeout: 12)
+        }
+    }
+
+    func test_dataTaskWithSharedDelegate() {
+        let sharedDelegate = SharedDelegate()
+        let urlString0 = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
+        let session = URLSession(configuration: .default, delegate: sharedDelegate, delegateQueue: nil)
+
+        let dataRequest = URLRequest(url: URL(string: urlString0)!)
+        let dataTask = session.dataTask(with: dataRequest)
+
+        sharedDelegate.dataCompletionExpectation = expectation(description: "GET \(urlString0)")
+        dataTask.resume()
+        waitForExpectations(timeout: 20)
+    }
+
+    func test_simpleUploadWithDelegate() {
+        let delegate = HTTPUploadDelegate()
+        let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
+        let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/upload"
+        var request = URLRequest(url: URL(string: urlString)!)
+        request.httpMethod = "PUT"
+
+        delegate.uploadCompletedExpectation = expectation(description: "PUT \(urlString): Upload data")
+
+        let fileData = Data(count: 16*1024)
+        let task = session.uploadTask(with: request, from: fileData)
+        task.resume()
+        waitForExpectations(timeout: 20)
+    }
 }
 
+class SharedDelegate: NSObject {
+    var dataCompletionExpectation: XCTestExpectation!
+}
+
+extension SharedDelegate: URLSessionDataDelegate {
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        dataCompletionExpectation.fulfill()
+    }
+}
+
+extension SharedDelegate: URLSessionDownloadDelegate {
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
+    }
+}
+
+
 class SessionDelegate: NSObject, URLSessionDelegate {
     let invalidateExpectation: XCTestExpectation
     init(invalidateExpectation: XCTestExpectation){
@@ -511,31 +608,6 @@
     }
 }
 
-class CustomProtocol : URLProtocol {
-    
-    override class func canInit(with request: URLRequest) -> Bool {
-        return true
-    }
-    
-    func sendResponse(statusCode: Int, headers: [String: String] = [:], data: Data) {
-        let response = HTTPURLResponse(url: self.request.url!, statusCode: statusCode, httpVersion: "HTTP/1.1", headerFields: headers)
-        self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
-        self.client?.urlProtocolDidFinishLoading(self)
-    }
-    
-    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
-        return request
-    }
-    
-    override func startLoading() {
-        sendResponse(statusCode: 429, data: Data())
-    }
-    
-    override func stopLoading() {
-        return
-    }
-}
-
 class HTTPRedirectionDataTask : NSObject {
     let dataTaskExpectation: XCTestExpectation!
     var session: URLSession! = nil
@@ -593,3 +665,21 @@
         completionHandler(request)
     }
 }
+
+class HTTPUploadDelegate: NSObject {
+    var uploadCompletedExpectation: XCTestExpectation!
+    var totalBytesSent: Int64 = 0
+}
+
+extension HTTPUploadDelegate: URLSessionTaskDelegate {
+    func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
+        self.totalBytesSent = totalBytesSent
+    }
+}
+
+extension HTTPUploadDelegate: URLSessionDataDelegate {
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        XCTAssertEqual(self.totalBytesSent, 16*1024)
+        uploadCompletedExpectation.fulfill()
+    }
+}
diff --git a/TestFoundation/TestNSXMLDocument.swift b/TestFoundation/TestNSXMLDocument.swift
index 5ebe9ee..728cc6c 100644
--- a/TestFoundation/TestNSXMLDocument.swift
+++ b/TestFoundation/TestNSXMLDocument.swift
@@ -41,7 +41,11 @@
                 ("test_dtd", test_dtd),
                 ("test_documentWithDTD", test_documentWithDTD),
                 ("test_dtd_attributes", test_dtd_attributes),
-                ("test_documentWithEncodingSetDoesntCrash", test_documentWithEncodingSetDoesntCrash)
+                ("test_documentWithEncodingSetDoesntCrash", test_documentWithEncodingSetDoesntCrash),
+                ("test_nodeFindingWithNamespaces", test_nodeFindingWithNamespaces),
+                ("test_createElement", test_createElement),
+                ("test_addNamespace", test_addNamespace),
+                ("test_removeNamespace", test_removeNamespace),
             ]
         #else // On Linux, currently the tests that rely on NSError are segfaulting in swift_dynamicCast
             return [
@@ -62,7 +66,11 @@
                 ("test_dtd", test_dtd),
                 //                ("test_documentWithDTD", test_documentWithDTD),
                 ("test_dtd_attributes", test_dtd_attributes),
-                ("test_documentWithEncodingSetDoesntCrash", test_documentWithEncodingSetDoesntCrash)
+                ("test_documentWithEncodingSetDoesntCrash", test_documentWithEncodingSetDoesntCrash),
+                ("test_nodeFindingWithNamespaces", test_nodeFindingWithNamespaces),
+                ("test_createElement", test_createElement),
+                ("test_addNamespace", test_addNamespace),
+                ("test_removeNamespace", test_removeNamespace),
             ]
         #endif
     }
@@ -79,6 +87,26 @@
         let element = doc.rootElement()!
         XCTAssert(element === node)
     }
+    
+    func test_createElement() throws {
+        let element = try XMLElement(xmlString: "<D:propfind xmlns:D=\"DAV:\"><D:prop></D:prop></D:propfind>")
+        XCTAssert(element.name! == "D:propfind")
+        XCTAssert(element.rootDocument == nil)
+        if let namespace = element.namespaces?.first {
+            XCTAssert(namespace.prefix == "D")
+            XCTAssert(namespace.stringValue == "DAV:")
+        } else {
+            XCTFail("Namespace was not parsed correctly")
+        }
+        
+        if let child = element.elements(forName: "D:prop").first {
+            XCTAssert(child.localName == "prop")
+            XCTAssert(child.prefix == "D")
+            XCTAssert(child.name == "D:prop")
+        } else {
+            XCTFail("Child element was not parsed correctly!")
+        }
+    }
 
     func test_nextPreviousNode() {
         let doc = XMLDocument(rootElement: nil)
@@ -93,18 +121,18 @@
         fooNode.addChild(bazNode)
         node.addChild(barNode)
 
-        XCTAssert(doc.nextNode === node)
-        XCTAssert(doc.nextNode?.nextNode === fooNode)
-        XCTAssert(doc.nextNode?.nextNode?.nextNode === bazNode)
-        XCTAssert(doc.nextNode?.nextNode?.nextNode?.nextNode === barNode)
+        XCTAssert(doc.next === node)
+        XCTAssert(doc.next?.next === fooNode)
+        XCTAssert(doc.next?.next?.next === bazNode)
+        XCTAssert(doc.next?.next?.next?.next === barNode)
 
-        XCTAssert(barNode.previousNode === bazNode)
-        XCTAssert(barNode.previousNode?.previousNode === fooNode)
-        XCTAssert(barNode.previousNode?.previousNode?.previousNode === node)
-        XCTAssert(barNode.previousNode?.previousNode?.previousNode?.previousNode === doc)
+        XCTAssert(barNode.previous === bazNode)
+        XCTAssert(barNode.previous?.previous === fooNode)
+        XCTAssert(barNode.previous?.previous?.previous === node)
+        XCTAssert(barNode.previous?.previous?.previous?.previous === doc)
     }
 
-    func test_xpath() {
+    func test_xpath() throws {
         let doc = XMLDocument(rootElement: nil)
         let foo = XMLElement(name: "foo")
         let bar1 = XMLElement(name: "bar")
@@ -117,20 +145,40 @@
         foo.addChild(bar2)
         foo.addChild(bar3)
         bar2.addChild(baz)
-
-        XCTAssertEqual(baz.xPath, "foo/bar[2]/baz")
-
-        let baz2 = XMLElement(name: "baz")
+        
+        XCTAssertEqual(baz.xPath, "/foo/bar[2]/baz")
+        
+        let baz2 = XMLElement(name: "/baz")
         bar2.addChild(baz2)
 
-        XCTAssertEqual(baz.xPath, "foo/bar[2]/baz[1]")
+        XCTAssertEqual(baz.xPath, "/foo/bar[2]/baz")
         XCTAssertEqual(try! doc.nodes(forXPath:baz.xPath!).first, baz)
 
-        let nodes = try! doc.nodes(forXPath:"foo/bar")
+        let nodes = try! doc.nodes(forXPath:"/foo/bar")
         XCTAssertEqual(nodes.count, 3)
         XCTAssertEqual(nodes[0], bar1)
         XCTAssertEqual(nodes[1], bar2)
         XCTAssertEqual(nodes[2], bar3)
+        
+        let xmlString = """
+        <?xml version="1.0" encoding="utf-8" standalone="yes"?>
+            <D:propfind xmlns:D="DAV:">
+                <D:prop>
+                    <D:getlastmodified></D:getlastmodified>
+                    <D:getcontentlength></D:getcontentlength>
+                    <D:creationdate></D:creationdate>
+                    <D:resourcetype></D:resourcetype>
+                </D:prop>
+            </D:propfind>
+        """
+        
+        let namespaceDoc = try XMLDocument(xmlString: xmlString, options: [])
+        let propNodes = try namespaceDoc.nodes(forXPath: "//D:prop")
+        if let propNode = propNodes.first {
+            XCTAssert(propNode.name == "D:prop")
+        } else {
+            XCTAssert(false, "propNode should have existed, but was nil")            
+        }
     }
 
     func test_elementCreation() {
@@ -152,7 +200,7 @@
         XCTAssertEqual(element.elements(forName:"bar"), [bar, bar2])
         XCTAssertFalse(element.elements(forName:"foo").contains(bar))
         XCTAssertFalse(element.elements(forName:"foo").contains(bar2))
-
+        
         let baz = XMLElement(name: "baz")
         element.insertChild(baz, at: 2)
         XCTAssertEqual(element.children?[2], baz)
@@ -290,6 +338,43 @@
         XCTAssertEqual(element.prefix, "xml")
         XCTAssertEqual(element.localName, "root")
     }
+    
+    func test_addNamespace() {
+        let doc = XMLDocument(rootElement: XMLElement(name: "Foo"))
+        let ns = XMLNode.namespace(withName: "F", stringValue: "http://example.com/fakenamespace") as! XMLNode
+        doc.rootElement()?.addNamespace(ns)
+        XCTAssert((doc.rootElement()?.namespaces ?? []).map({ $0.stringValue ?? "foo" }).contains(ns.stringValue ?? "bar"), "namespaces didn't include the added namespace!")
+        XCTAssert(doc.rootElement()?.uri == "http://example.com/fakenamespace", "uri was \(doc.rootElement()?.uri ?? "null") instead of http://example.com/fakenamespace")
+        
+        let otherNS = XMLNode.namespace(withName: "R", stringValue: "http://example.com/rnamespace") as! XMLNode
+        doc.rootElement()?.addNamespace(otherNS)
+        XCTAssert((doc.rootElement()?.namespaces ?? []).map({ $0.stringValue ?? "foo" }).contains(ns.stringValue ?? "bar"), "lost original namespace")
+        XCTAssert((doc.rootElement()?.namespaces ?? []).map({ $0.stringValue ?? "foo" }).contains(otherNS.stringValue ?? "bar"), "Lost new namespace")
+        doc.rootElement()?.addNamespace(XMLNode.namespace(withName: "R", stringValue: "http://example.com/rnamespace") as! XMLNode)
+        XCTAssert(doc.rootElement()?.namespaces?.count == 2, "incorrectly added a namespace with duplicate name!")
+        
+        let otherDoc = XMLDocument(rootElement: XMLElement(name: "Bar"))
+        otherDoc.rootElement()?.namespaces = [XMLNode.namespace(withName: "R", stringValue: "http://example.com/rnamespace") as! XMLNode, XMLNode.namespace(withName: "F", stringValue: "http://example.com/fakenamespace") as! XMLNode]
+        XCTAssert(otherDoc.rootElement()?.namespaces?.count == 2)
+        XCTAssert(otherDoc.rootElement()?.namespaces?.flatMap({ $0.name })[0] == "R" && otherDoc.rootElement()?.namespaces?.flatMap({ $0.name })[1] == "F")
+        otherDoc.rootElement()?.namespaces = nil
+        XCTAssert((otherDoc.rootElement()?.namespaces?.count ?? 0) == 0)
+    }
+    
+    func test_removeNamespace() {
+        let doc = XMLDocument(rootElement: XMLElement(name: "Foo"))
+        let ns = XMLNode.namespace(withName: "F", stringValue: "http://example.com/fakenamespace") as! XMLNode
+        let otherNS = XMLNode.namespace(withName: "R", stringValue: "http://example.com/rnamespace") as! XMLNode
+        
+        doc.rootElement()?.addNamespace(ns)
+        doc.rootElement()?.addNamespace(otherNS)
+        XCTAssert(doc.rootElement()?.namespaces?.count == 2)
+        
+        doc.rootElement()?.removeNamespace(forPrefix: "F")
+        
+        XCTAssert(doc.rootElement()?.namespaces?.count == 1)
+        XCTAssert(doc.rootElement()?.namespaces?.first?.name == "R")
+    }
 
     /*
      * <rdar://31567922> Re-enable these tests in a way that does not depend on the internet.
@@ -339,7 +424,7 @@
     func test_dtd() throws {
         let node = XMLNode.dtdNode(withXMLString:"<!ELEMENT foo (#PCDATA)>") as! XMLDTDNode
         XCTAssert(node.name == "foo")
-
+        
         let dtd = try XMLDTD(contentsOf: testBundle().url(forResource: "PropertyList-1.0", withExtension: "dtd")!, options: [])
         //        dtd.systemID = testBundle().URLForResource("PropertyList-1.0", withExtension: "dtd")?.absoluteString
         dtd.name = "plist"
@@ -372,13 +457,14 @@
         elementDecl.name = "MyElement"
         elementDecl.stringValue = "(#PCDATA | array)*"
         XCTAssert(elementDecl.stringValue == "(#PCDATA | array)*", elementDecl.stringValue ?? "nil string value")
+        XCTAssert(elementDecl.name == "MyElement")
     }
 
     func test_documentWithDTD() throws {
         let doc = try XMLDocument(contentsOf: testBundle().url(forResource: "NSXMLDTDTestData", withExtension: "xml")!, options: [])
         let dtd = doc.dtd
         XCTAssert(dtd?.name == "root")
-
+        
         let notation = dtd?.notationDeclaration(forName:"myNotation")
         notation?.detach()
         XCTAssert(notation?.name == "myNotation")
@@ -419,5 +505,66 @@
         makeSureDocumentIsAllocatedAndFreed()
         XCTAssertNil(weakDoc, "document not freed even through it should have")
     }
-
+    
+    func test_nodeFindingWithNamespaces() throws {
+        let xmlString = """
+        <?xml version="1.0" encoding="utf-8" standalone="yes"?>
+            <D:propfind xmlns:D="DAV:">
+                <D:prop>
+                    <D:getlastmodified></D:getlastmodified>
+                    <D:getcontentlength></D:getcontentlength>
+                    <D:creationdate></D:creationdate>
+                    <D:resourcetype></D:resourcetype>
+                </D:prop>
+            </D:propfind>
+        """
+        
+        let doc = try XMLDocument(xmlString: xmlString, options: [])
+        let namespace = (doc.rootElement()?.namespaces?.first)!
+        XCTAssert(namespace.kind == .namespace, "The node was not a namespace but was a \(namespace.kind)")
+        XCTAssert(namespace.stringValue == "DAV:", "expected a string value of DAV: got \(namespace.stringValue as Any)")
+        XCTAssert(namespace.name == "D", "expected a name of D, got \(namespace.name as Any)")
+        
+        let newNS = XMLNode.namespace(withName: "R", stringValue: "http://apple.com") as! XMLNode
+        XCTAssert(newNS.name == "R", "expected name R, got name \(newNS.name as Any)")
+        XCTAssert(newNS.stringValue == "http://apple.com", "expected stringValue http://apple.com, got stringValue \(newNS.stringValue as Any)")
+        newNS.stringValue = "FOO:"
+        XCTAssert(newNS.stringValue == "FOO:")
+        newNS.name = "F"
+        XCTAssert(newNS.name == "F")
+        
+        let root = doc.rootElement()!
+        XCTAssert(root.localName == "propfind")
+        XCTAssert(root.name == "D:propfind")
+        XCTAssert(root.prefix == "D")
+        let node = doc.findFirstChild(named: "prop")
+        XCTAssert(node != nil, "failed to find existing node")
+        XCTAssert(node?.localName == "prop")
+        
+        XCTAssert(doc.rootElement()?.elements(forLocalName: "prop", uri: "DAV:").first?.name == "D:prop", "failed to get elements, got \(doc.rootElement()?.elements(forLocalName: "prop", uri: "DAV:").first as Any)")
+    }
 }
+
+fileprivate extension XMLNode {
+    fileprivate func findFirstChild(named name: String) -> XMLNode? {
+        guard let children = self.children else {
+            return nil
+        }
+        
+        for child in children {
+            if let childName = child.localName {
+                if childName == name {
+                    return child
+                }
+            }
+            
+            if let result = child.findFirstChild(named: name) {
+                return result
+            }
+        }
+        
+        return nil
+    }
+}
+
+
diff --git a/TestFoundation/TestProcess.swift b/TestFoundation/TestProcess.swift
index cbac7a9..163dc31 100644
--- a/TestFoundation/TestProcess.swift
+++ b/TestFoundation/TestProcess.swift
@@ -28,6 +28,7 @@
                    ("test_pipe_stdin", test_pipe_stdin),
                    ("test_pipe_stdout", test_pipe_stdout),
                    ("test_pipe_stderr", test_pipe_stderr),
+                   ("test_current_working_directory", test_current_working_directory),
                    // disabled for now
                    // ("test_pipe_stdout_and_stderr_same_pipe", test_pipe_stdout_and_stderr_same_pipe),
                    ("test_file_stdout", test_file_stdout),
@@ -262,6 +263,19 @@
             XCTFail("Test failed: \(error)")
         }
     }
+
+    func test_current_working_directory() {
+        do {
+            let previousWorkingDirectory = FileManager.default.currentDirectoryPath
+
+            // `bash` will not be found if the current working directory is not set correctly.
+            let _ = try runTask(["bash", "-c", "exit 0"], currentDirectoryPath: "/bin")
+
+            XCTAssertEqual(previousWorkingDirectory, FileManager.default.currentDirectoryPath)
+        } catch let error {
+            XCTFail("Test failed: \(error)")
+        }
+    }
 }
 
 private func mkstemp(template: String, body: (FileHandle) throws -> Void) rethrows {
@@ -284,7 +298,7 @@
     case InvalidEnvironmentVariable(String)
 }
 
-private func runTask(_ arguments: [String], environment: [String: String]? = nil) throws -> String {
+private func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> String {
     let process = Process()
 
     var arguments = arguments
@@ -292,6 +306,10 @@
     process.arguments = arguments
     process.environment = environment
 
+    if let directoryPath = currentDirectoryPath {
+        process.currentDirectoryPath = directoryPath
+    }
+
     let pipe = Pipe()
     process.standardOutput = pipe
     process.standardError = pipe
diff --git a/TestFoundation/main.swift b/TestFoundation/main.swift
index 1bbdeb0..5788e03 100644
--- a/TestFoundation/main.swift
+++ b/TestFoundation/main.swift
@@ -10,15 +10,20 @@
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
 import Foundation
 import XCTest
+import Glibc
 #else
 import SwiftFoundation
 import SwiftXCTest
+import Darwin
 #endif
 
 internal func testBundle() -> Bundle {
     return Bundle.main
 }
 
+// ignore SIGPIPE which is sent when writing to closed file descriptors.
+_ = signal(SIGPIPE, SIG_IGN)
+
 // For the Swift version of the Foundation tests, we must manually list all test cases here.
 XCTMain([
     testCase(TestNSAffineTransform.allTests),
@@ -76,6 +81,7 @@
     testCase(TestNSURL.allTests),
     testCase(TestNSURLComponents.allTests),
     testCase(TestNSURLCredential.allTests),
+    testCase(TestNSURLProtocol.allTests),
     testCase(TestNSURLRequest.allTests),
     testCase(TestURLRequest.allTests),
     testCase(TestNSURLResponse.allTests),
@@ -97,4 +103,5 @@
     testCase(TestNotification.allTests),
     testCase(TestMassFormatter.allTests),
     testCase(TestJSONEncoder.allTests),
+    testCase(TestCodable.allTests),
 ])
diff --git a/lib/product.py b/lib/product.py
index f4c85f6..3e9e432 100644
--- a/lib/product.py
+++ b/lib/product.py
@@ -182,6 +182,8 @@
     def generate(self, objects = []):
         self.rule = "Archive"
         self.product_name = Configuration.current.target.static_library_prefix + self.name + Configuration.current.target.static_library_suffix
+        self.conformance_begin = ''
+        self.conformance_end = ''
         return Library.generate(self, [], objects)
 
 class StaticAndDynamicLibrary(StaticLibrary, DynamicLibrary):