11public extension View {
22 consuming func environment< V> ( _ key: EnvironmentValues . _Key < V > , _ value: V ) -> _EnvironmentView < V , Self > {
3- _EnvironmentView ( wrapped: self , key: key, value: value)
3+ _EnvironmentView ( wrapped: self , key: key, value: value, isEqual: nil )
4+ }
5+
6+ consuming func environment< V> ( _ key: EnvironmentValues . _Key < V > , _ value: V ) -> _EnvironmentView < V , Self >
7+ where V: Equatable {
8+ _EnvironmentView ( wrapped: self , key: key, value: value, isEqual: == )
9+ }
10+
11+ consuming func environment( _ key: EnvironmentValues . _Key < String > , _ value: String ) -> _EnvironmentView < String , Self > {
12+ _EnvironmentView ( wrapped: self , key: key, value: value, isEqual: String . utf8Equals)
13+ }
14+
15+ consuming func environment< V> ( _ key: EnvironmentValues . _Key < V > , _ value: V ) -> _EnvironmentView < V , Self >
16+ where V: Equatable & AnyObject {
17+ _EnvironmentView ( wrapped: self , key: key, value: value, isEqual: === )
18+ }
19+
20+ consuming func environment< V> ( _ key: EnvironmentValues . _Key < V > , _ value: V ) -> _EnvironmentView < V , Self >
21+ where V: AnyObject {
22+ _EnvironmentView ( wrapped: self , key: key, value: value, isEqual: === )
423 }
524
625 consuming func environment< V: ReactiveObject > ( _ object: V ) -> _EnvironmentView < V , Self > {
7- _EnvironmentView ( wrapped: self , key: V . environmentKey, value: object)
26+ _EnvironmentView ( wrapped: self , key: V . environmentKey, value: object, isEqual : === )
827 }
928}
1029
1130public struct _EnvironmentView < V, Wrapped: View > : View {
12- public typealias _MountedNode = Wrapped . _MountedNode
13-
31+ public typealias _MountedNode = _StatefulNode < EnvironmentValues . _Box < V > , Wrapped . _MountedNode >
1432 public typealias Tag = Wrapped . Tag
33+
1534 let wrapped : Wrapped
1635 let key : EnvironmentValues . _Key < V >
1736 let value : V
37+ let isEqual : ( ( V , V ) -> Bool ) ?
1838
1939 public static func _makeNode(
2040 _ view: consuming Self ,
2141 context: consuming _ViewContext ,
2242 reconciler: inout _RenderContext
2343 ) -> _MountedNode {
24- context. environment [ view. key] = view. value
25- return Wrapped . _makeNode ( view. wrapped, context: context, reconciler: & reconciler)
44+
45+ let box = EnvironmentValues . _Box< V> ( view. value)
46+ context. environment. boxes [ view. key. propertyID] = box
47+
48+ return . init( state: box, child: Wrapped . _makeNode ( view. wrapped, context: context, reconciler: & reconciler) )
2649 }
2750
2851 public static func _patchNode(
@@ -31,7 +54,20 @@ public struct _EnvironmentView<V, Wrapped: View>: View {
3154 node: inout _MountedNode ,
3255 reconciler: inout _RenderContext
3356 ) {
34- context. environment [ view. key] = view. value
35- Wrapped . _patchNode ( view. wrapped, context: context, node: & node, reconciler: & reconciler)
57+ // IMPORTANT: _value does not cause access tracking!
58+ if view. isEqual ? ( node. state. _value, view. value) ?? true {
59+ node. state. _value = view. value
60+ } else {
61+ // NOTE: a bit of a hack to allow dependent functions to run in the same reconciler run
62+ reconciler. scheduler. withAmbientRenderContext (
63+ & reconciler,
64+ {
65+ node. state. value = view. value
66+ }
67+ )
68+ }
69+
70+ context. environment. boxes [ view. key. propertyID] = node. state
71+ Wrapped . _patchNode ( view. wrapped, context: context, node: & node. child, reconciler: & reconciler)
3672 }
3773}
0 commit comments