This reproposes @lilyball’s fixes in https://github.com/apple/swift/pull/20103 while adding her fix to ensure observations are removed before observed objects in 32-bit testing.
The global table was vulnerable to race conditions when making
observations concurrently on multiple threads. We can assume the
`NSKeyValueObservingCustomization` methods are invoked synchronously
when creating the observation, so we can use a per-thread table instead.
This per-thread table is still vulnerable in the event that an
implementation of `automaticallyNotifiesObservers(for:)` creates a new
observation using a different `KeyPath` with the same Obj-C path, but
this method really shouldn't be creating any observations of its own.
Unfortunately we can't include the class in the per-thread table key, as
this may produce incorrect results in the presence of subclasses.
rdar://problem/45567020 https://bugs.swift.org/browse/SR-9077
The previous implementation could return keyPaths other than the one
used to create the `NSSortDescriptor` in the event that any subsequent
observation, `NSExpression`, or `NSSortDescriptor` was created using a
different `KeyPath` that had the same Obj-C keypath value.
https://bugs.swift.org/browse/SR-9076
If the `NSKeyValueObservation` was being deinited on one thread while a
KVO change notice was being broadcast on another, it could end up trying
to handle the change notice concurrently with deiniting, which will
probably crash.
This also fixes a problem where it was swizzling `NSObject`'s
`observeValue(forKeyPath:of:change:context:)` implementation, which
resulted in potentially invoking undefined behavior if an observer ever
called up to `NSObject`'s implementation.
https://bugs.swift.org/browse/SR-9074https://bugs.swift.org/browse/SR-9075
Swizzling the methods in a different order ensures we don't overwrite
the public `NSObject` method until it's safe to call our replacement.
rdar://problem/36663633 https://bugs.swift.org/browse/SR-6795
The SDK directory is now confusing as the Windows target also has a SDK
overlay. In order to make this more uniform, move the SDK directory to
Darwin which covers the fact that this covers the XNU family of OSes.
The Windows directory contains the SDK overlay for the Windows target.