@playfast/reform 1.3.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -6
- package/dist/calc/asyncCalc.d.ts +3 -1
- package/dist/calc/asyncCalc.d.ts.map +1 -1
- package/dist/calc/asyncCalc.js +15 -5
- package/dist/calc/asyncCalc.js.map +1 -1
- package/dist/calc/asyncCalcTypes.d.ts +2 -0
- package/dist/calc/asyncCalcTypes.d.ts.map +1 -1
- package/dist/calc/calcFamily.d.ts.map +1 -1
- package/dist/calc/calcFamily.js +77 -34
- package/dist/calc/calcFamily.js.map +1 -1
- package/dist/calc/queryState.d.ts +3 -1
- package/dist/calc/queryState.d.ts.map +1 -1
- package/dist/calc/queryState.js +31 -9
- package/dist/calc/queryState.js.map +1 -1
- package/dist/channel/channel.d.ts.map +1 -1
- package/dist/channel/channel.js +6 -1
- package/dist/channel/channel.js.map +1 -1
- package/dist/compose/composition.d.ts.map +1 -1
- package/dist/compose/composition.js +7 -1
- package/dist/compose/composition.js.map +1 -1
- package/dist/compose/structure.d.ts.map +1 -1
- package/dist/compose/structure.js +33 -8
- package/dist/compose/structure.js.map +1 -1
- package/dist/compose/ui.d.ts.map +1 -1
- package/dist/compose/ui.js +16 -5
- package/dist/compose/ui.js.map +1 -1
- package/dist/event/event.d.ts +1 -1
- package/dist/event/event.d.ts.map +1 -1
- package/dist/event/event.js +26 -4
- package/dist/event/event.js.map +1 -1
- package/dist/internal/familyKeys.d.ts +16 -0
- package/dist/internal/familyKeys.d.ts.map +1 -0
- package/dist/internal/familyKeys.js +35 -0
- package/dist/internal/familyKeys.js.map +1 -0
- package/dist/internal/platform.d.ts +43 -0
- package/dist/internal/platform.d.ts.map +1 -0
- package/dist/internal/platform.js +68 -0
- package/dist/internal/platform.js.map +1 -0
- package/dist/internal/queryDriver.d.ts.map +1 -1
- package/dist/internal/queryDriver.js +88 -64
- package/dist/internal/queryDriver.js.map +1 -1
- package/dist/internal/queryDriverConsume.d.ts +9 -0
- package/dist/internal/queryDriverConsume.d.ts.map +1 -0
- package/dist/internal/queryDriverConsume.js +16 -0
- package/dist/internal/queryDriverConsume.js.map +1 -0
- package/dist/internal/queryDriverHydrate.d.ts.map +1 -1
- package/dist/internal/queryDriverHydrate.js +9 -3
- package/dist/internal/queryDriverHydrate.js.map +1 -1
- package/dist/internal/queryDriverPersist.d.ts +16 -0
- package/dist/internal/queryDriverPersist.d.ts.map +1 -0
- package/dist/internal/queryDriverPersist.js +15 -0
- package/dist/internal/queryDriverPersist.js.map +1 -0
- package/dist/internal/queryDriverPersistWarn.d.ts +12 -0
- package/dist/internal/queryDriverPersistWarn.d.ts.map +1 -0
- package/dist/internal/queryDriverPersistWarn.js +31 -0
- package/dist/internal/queryDriverPersistWarn.js.map +1 -0
- package/dist/internal/queryDriverSettle.d.ts +23 -0
- package/dist/internal/queryDriverSettle.d.ts.map +1 -0
- package/dist/internal/queryDriverSettle.js +52 -0
- package/dist/internal/queryDriverSettle.js.map +1 -0
- package/dist/internal/queryDriverStore.d.ts +2 -28
- package/dist/internal/queryDriverStore.d.ts.map +1 -1
- package/dist/internal/queryDriverStore.js +5 -29
- package/dist/internal/queryDriverStore.js.map +1 -1
- package/dist/internal/queryDriverTypes.d.ts +3 -0
- package/dist/internal/queryDriverTypes.d.ts.map +1 -1
- package/dist/internal/scheduler.d.ts +1 -0
- package/dist/internal/scheduler.d.ts.map +1 -1
- package/dist/internal/scheduler.js +69 -6
- package/dist/internal/scheduler.js.map +1 -1
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +4 -0
- package/dist/internal.js.map +1 -1
- package/dist/reducer/reducer.js +3 -3
- package/dist/reducer/reducer.js.map +1 -1
- package/dist/remote/pendingQueue.d.ts +4 -2
- package/dist/remote/pendingQueue.d.ts.map +1 -1
- package/dist/remote/pendingQueue.js +20 -4
- package/dist/remote/pendingQueue.js.map +1 -1
- package/dist/remote/remoteState.d.ts.map +1 -1
- package/dist/remote/remoteState.js +27 -14
- package/dist/remote/remoteState.js.map +1 -1
- package/dist/remote/remoteStateSend.d.ts +3 -1
- package/dist/remote/remoteStateSend.d.ts.map +1 -1
- package/dist/remote/remoteStateSend.js +19 -3
- package/dist/remote/remoteStateSend.js.map +1 -1
- package/dist/remote/remoteStateTypes.d.ts +3 -0
- package/dist/remote/remoteStateTypes.d.ts.map +1 -1
- package/dist/runtime/bus.d.ts +5 -0
- package/dist/runtime/bus.d.ts.map +1 -1
- package/dist/runtime/bus.js +1 -1
- package/dist/runtime/bus.js.map +1 -1
- package/dist/runtime/capturedAppRuntime.d.ts.map +1 -1
- package/dist/runtime/capturedAppRuntime.js +37 -51
- package/dist/runtime/capturedAppRuntime.js.map +1 -1
- package/dist/runtime/eventBudget.d.ts.map +1 -1
- package/dist/runtime/eventBudget.js +2 -1
- package/dist/runtime/eventBudget.js.map +1 -1
- package/dist/runtime/featureMount.d.ts +34 -2
- package/dist/runtime/featureMount.d.ts.map +1 -1
- package/dist/runtime/featureMount.js +66 -2
- package/dist/runtime/featureMount.js.map +1 -1
- package/dist/runtime/loop.d.ts +12 -0
- package/dist/runtime/loop.d.ts.map +1 -1
- package/dist/runtime/loop.js +8 -5
- package/dist/runtime/loop.js.map +1 -1
- package/dist/state/state.d.ts +2 -2
- package/dist/state/state.d.ts.map +1 -1
- package/dist/state/state.js +2 -2
- package/dist/state/state.js.map +1 -1
- package/dist/state/stateFamily.d.ts +2 -2
- package/dist/state/stateFamily.d.ts.map +1 -1
- package/dist/state/stateFamily.js +80 -32
- package/dist/state/stateFamily.js.map +1 -1
- package/dist/state/stateGroup.d.ts +5 -5
- package/dist/state/stateGroup.d.ts.map +1 -1
- package/dist/state/stateGroup.js +1 -1
- package/dist/state/stateGroup.js.map +1 -1
- package/dist/testkit/flight.testkit.d.ts.map +1 -1
- package/dist/testkit/flight.testkit.js +2 -1
- package/dist/testkit/flight.testkit.js.map +1 -1
- package/dist/ui/trigger.d.ts +3 -0
- package/dist/ui/trigger.d.ts.map +1 -1
- package/dist/ui/trigger.js +14 -1
- package/dist/ui/trigger.js.map +1 -1
- package/dist/wire/tree.d.ts.map +1 -1
- package/dist/wire/tree.js +6 -1
- package/dist/wire/tree.js.map +1 -1
- package/package.json +1 -1
- package/src/calc/asyncCalc-key-attribution.test.ts +182 -0
- package/src/calc/asyncCalc-registry-name.test.ts +82 -0
- package/src/calc/asyncCalc.superseded-commit.test.ts +162 -0
- package/src/calc/asyncCalc.test.ts +35 -7
- package/src/calc/asyncCalc.ts +33 -10
- package/src/calc/asyncCalcTypes.ts +6 -0
- package/src/calc/calcFamily.ts +81 -34
- package/src/calc/family-identity.test.ts +231 -0
- package/src/calc/queryState.ts +36 -5
- package/src/channel/channel-throttle-frames.test.ts +163 -0
- package/src/channel/channel.ts +5 -0
- package/src/compose/compose-identity.test.ts +175 -0
- package/src/compose/composition.ts +8 -4
- package/src/compose/structure.ts +45 -13
- package/src/compose/ui.ts +22 -5
- package/src/event/event.ts +34 -5
- package/src/event/syncTrigger.test.ts +66 -0
- package/src/internal/familyKeys.ts +41 -0
- package/src/internal/platform.test.ts +55 -0
- package/src/internal/platform.ts +72 -0
- package/src/internal/queryDriver-defect-attribution.test.ts +107 -0
- package/src/internal/queryDriver-persist-key.test.ts +118 -0
- package/src/internal/queryDriver.persistence-staleness.test.ts +209 -0
- package/src/internal/queryDriver.ts +92 -80
- package/src/internal/queryDriverConsume.ts +42 -0
- package/src/internal/queryDriverHydrate.ts +9 -3
- package/src/internal/queryDriverPersist.ts +42 -0
- package/src/internal/queryDriverPersistWarn.ts +61 -0
- package/src/internal/queryDriverSettle.ts +85 -0
- package/src/internal/queryDriverStore.ts +9 -74
- package/src/internal/queryDriverTypes.ts +10 -0
- package/src/internal/queryState-and-scheduler-audit.test.ts +170 -0
- package/src/internal/scheduler-multi-source-wake.test.ts +111 -0
- package/src/internal/scheduler.ts +80 -6
- package/src/internal.ts +4 -0
- package/src/reducer/reducer.ts +3 -3
- package/src/remote/pendingQueue.ts +35 -5
- package/src/remote/remoteState.intent-key-stamp.test.ts +207 -0
- package/src/remote/remoteState.key-attribution.test.ts +174 -0
- package/src/remote/remoteState.ts +27 -15
- package/src/remote/remoteStateSend.ts +29 -8
- package/src/remote/remoteStateTypes.ts +7 -0
- package/src/runtime/bus.ts +6 -1
- package/src/runtime/capturedAppRuntime.ts +134 -110
- package/src/runtime/eventBudget.ts +2 -1
- package/src/runtime/feature-mount-ownership.test.ts +539 -0
- package/src/runtime/featureMount.ts +110 -3
- package/src/runtime/loop.ts +29 -6
- package/src/runtime/mount-inflight-ownership.test.ts +361 -0
- package/src/runtime/mount-scope-hardening.test.ts +440 -0
- package/src/runtime/runtime.schema-identity.test.ts +188 -0
- package/src/state/state.ts +8 -4
- package/src/state/stateFamily.ts +86 -36
- package/src/state/stateGroup.ts +24 -6
- package/src/testkit/flight.testkit.ts +2 -1
- package/src/ui/trigger.ts +18 -0
- package/src/wire/tree-key-presence.test.ts +46 -0
- package/src/wire/tree.ts +9 -1
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Context,
|
|
3
|
+
Effect,
|
|
4
|
+
ExecutionStrategy,
|
|
5
|
+
Exit,
|
|
6
|
+
Layer,
|
|
7
|
+
ManagedRuntime,
|
|
8
|
+
Option,
|
|
9
|
+
Scope,
|
|
10
|
+
} from 'effect'
|
|
11
|
+
import type {
|
|
12
|
+
CompositionActivation,
|
|
13
|
+
CompositionId,
|
|
14
|
+
RequiredSlotIdentities,
|
|
15
|
+
} from '../compose/composition'
|
|
3
16
|
import type { UiContract } from '../compose/ui'
|
|
4
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
type AnyFeatureBinding,
|
|
19
|
+
type CapturedFeatureBinding,
|
|
20
|
+
type FeatureBinding,
|
|
21
|
+
FeatureInput,
|
|
22
|
+
type FeatureRequirement,
|
|
23
|
+
} from '../feature/feature'
|
|
5
24
|
import type {
|
|
6
25
|
AnyFeatureGraphSummary,
|
|
7
26
|
FeatureSummaryCompositionIdentity,
|
|
@@ -17,7 +36,16 @@ import { type Node } from '../ui/node'
|
|
|
17
36
|
import { type CapturedScene, sceneInstrumentation } from '../scene/scene'
|
|
18
37
|
import { Bus, publish, type Priority, type Tagged } from './bus'
|
|
19
38
|
import { CurrentEventBudget, type ReformOptions, resolveEventBudget } from './eventBudget'
|
|
20
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
invalidMountProps,
|
|
41
|
+
missingHostServices,
|
|
42
|
+
type FeatureMountHost,
|
|
43
|
+
forkFeatureMount,
|
|
44
|
+
hasFeatureRequirements,
|
|
45
|
+
mountActivation,
|
|
46
|
+
startMount,
|
|
47
|
+
withInstrumentation,
|
|
48
|
+
} from './featureMount'
|
|
21
49
|
import type {
|
|
22
50
|
AnyFeatureMountHandlers,
|
|
23
51
|
AppRuntime,
|
|
@@ -52,8 +80,15 @@ export const makeCapturedAppRuntime = <
|
|
|
52
80
|
// Hosts can still render tearing-down trees after the managed runtime is disposed.
|
|
53
81
|
const status = { disposed: false, booted: false }
|
|
54
82
|
const activationDisposers = new Set<() => void>()
|
|
55
|
-
|
|
56
|
-
|
|
83
|
+
// Everything this runtime mounts is forked from here, so `dispose()` closes it all
|
|
84
|
+
// without having to be handed each mount's disposer. A forked scope deregisters
|
|
85
|
+
// itself from its owner when it closes first, so churn does not accumulate.
|
|
86
|
+
// Parallel: the root's finalizers are one independent mount each, so a teardown that
|
|
87
|
+
// takes a turn must not withhold its siblings'.
|
|
88
|
+
const rootScope = Effect.runSync(Scope.make(ExecutionStrategy.parallel))
|
|
89
|
+
const instrumented = withInstrumentation(instrumentation)
|
|
90
|
+
const mountHost: FeatureMountHost = {
|
|
91
|
+
runFork: <A>(effect: Effect.Effect<A, never, never>) => runtime.runFork(effect),
|
|
57
92
|
isDisposed: () => status.disposed,
|
|
58
93
|
}
|
|
59
94
|
|
|
@@ -68,33 +103,22 @@ export const makeCapturedAppRuntime = <
|
|
|
68
103
|
runtime.runFork(publish(priority, event).pipe(Effect.provideService(Bus, rootBus.value)))
|
|
69
104
|
}
|
|
70
105
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Layer.build(activation)
|
|
106
|
+
const mountScopedOnto = (
|
|
107
|
+
ownerScope: Scope.Scope,
|
|
108
|
+
activation: CompositionActivation,
|
|
109
|
+
): (() => void) =>
|
|
110
|
+
mountActivation(
|
|
111
|
+
mountHost,
|
|
112
|
+
activationDisposers,
|
|
113
|
+
instrumented(Layer.build(activation)),
|
|
114
|
+
ownerScope,
|
|
79
115
|
)
|
|
80
|
-
const dispose = (): void => {
|
|
81
|
-
if (!liveness.active) {
|
|
82
|
-
return
|
|
83
|
-
}
|
|
84
|
-
liveness.active = false
|
|
85
|
-
fiber.unsafeInterruptAsFork(fiber.id())
|
|
86
|
-
const close = Fiber.await(fiber).pipe(
|
|
87
|
-
Effect.zipRight(Scope.close(scope, Exit.succeed(undefined))),
|
|
88
|
-
Effect.ensuring(Effect.sync(() => activationDisposers.delete(dispose))),
|
|
89
|
-
)
|
|
90
|
-
Effect.runFork(close)
|
|
91
|
-
}
|
|
92
|
-
activationDisposers.add(dispose)
|
|
93
|
-
return dispose
|
|
94
|
-
}
|
|
95
116
|
|
|
117
|
+
// A feature's handle mounts into the feature's own scope: whatever it mounts must
|
|
118
|
+
// not outlive the context it was built against.
|
|
96
119
|
const makeChildRuntime = <ChildServices>(
|
|
97
120
|
context: Context.Context<ChildServices>,
|
|
121
|
+
ownerScope: Scope.Scope,
|
|
98
122
|
): RuntimeHandle<ChildServices> => ({
|
|
99
123
|
read: <Identifier extends ChildServices, Service>(
|
|
100
124
|
tag: Context.Tag<Identifier, Service>,
|
|
@@ -104,11 +128,12 @@ export const makeCapturedAppRuntime = <
|
|
|
104
128
|
): Option.Option<Service> => Context.getOption(context, tag),
|
|
105
129
|
runRender,
|
|
106
130
|
dispatch,
|
|
107
|
-
mountScoped,
|
|
108
|
-
mountFeature: (binding, handlers) => mountFeatureOnto(context, binding, handlers),
|
|
131
|
+
mountScoped: (activation) => mountScopedOnto(ownerScope, activation),
|
|
132
|
+
mountFeature: (binding, handlers) => mountFeatureOnto(context, ownerScope, binding, handlers),
|
|
109
133
|
mountCapturedFeature: (binding, handlers) =>
|
|
110
|
-
mountCapturedFeatureOnto(context, binding, handlers),
|
|
111
|
-
mountAnyFeature: (binding, handlers) =>
|
|
134
|
+
mountCapturedFeatureOnto(context, ownerScope, binding, handlers),
|
|
135
|
+
mountAnyFeature: (binding, handlers) =>
|
|
136
|
+
mountAnyFeatureOnto(context, ownerScope, binding, handlers),
|
|
112
137
|
instrumentation,
|
|
113
138
|
})
|
|
114
139
|
|
|
@@ -119,6 +144,7 @@ export const makeCapturedAppRuntime = <
|
|
|
119
144
|
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
120
145
|
>(
|
|
121
146
|
hostContext: Context.Context<HostServices>,
|
|
147
|
+
ownerScope: Scope.Scope,
|
|
122
148
|
binding: FeatureBinding<Summary, ROut, DirectRequires>,
|
|
123
149
|
handlers: FeatureMountHandlers<
|
|
124
150
|
FeatureSummaryUsesInput<Summary>,
|
|
@@ -126,37 +152,35 @@ export const makeCapturedAppRuntime = <
|
|
|
126
152
|
HostServices | ROut
|
|
127
153
|
>,
|
|
128
154
|
): (() => void) => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
hostContext,
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return Effect.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}).pipe(Effect.provideService(Bus, bus))
|
|
155
|
-
const merged = Context.merge(hostContext, context)
|
|
156
|
-
yield* Effect.sync(() => handlers.onLive(makeChildRuntime<HostServices | ROut>(merged)))
|
|
155
|
+
const mountInto = (scope: Scope.CloseableScope) =>
|
|
156
|
+
Effect.flatMap(binding.load, (loaded) => {
|
|
157
|
+
if (
|
|
158
|
+
!hasFeatureRequirements<
|
|
159
|
+
HostServices,
|
|
160
|
+
FeatureSummaryOpenServices<Summary>,
|
|
161
|
+
DirectRequires
|
|
162
|
+
>(hostContext, loaded.requires)
|
|
163
|
+
) {
|
|
164
|
+
return missingHostServices(binding.manifest.name)
|
|
165
|
+
}
|
|
166
|
+
return Effect.gen(function* () {
|
|
167
|
+
const bus = Context.get(hostContext, Bus)
|
|
168
|
+
const featureContext = Context.add(hostContext, FeatureInput, handlers.props)
|
|
169
|
+
const context = yield* Layer.build(
|
|
170
|
+
Layer.provide(loaded.layer, Layer.succeedContext(featureContext)),
|
|
171
|
+
)
|
|
172
|
+
yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
|
|
173
|
+
discard: true,
|
|
174
|
+
}).pipe(Effect.provideService(Bus, bus))
|
|
175
|
+
const merged = Context.merge(hostContext, context)
|
|
176
|
+
yield* Effect.sync(() =>
|
|
177
|
+
handlers.onLive(makeChildRuntime<HostServices | ROut>(merged, scope)),
|
|
178
|
+
)
|
|
179
|
+
})
|
|
157
180
|
})
|
|
158
|
-
|
|
159
|
-
|
|
181
|
+
return startMount(mountHost, ownerScope, (scope) =>
|
|
182
|
+
forkFeatureMount(mountHost, scope, instrumented(mountInto(scope)), handlers.onFailed),
|
|
183
|
+
)
|
|
160
184
|
}
|
|
161
185
|
|
|
162
186
|
const mountCapturedFeatureOnto = <
|
|
@@ -166,6 +190,7 @@ export const makeCapturedAppRuntime = <
|
|
|
166
190
|
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
167
191
|
>(
|
|
168
192
|
hostContext: Context.Context<HostServices>,
|
|
193
|
+
ownerScope: Scope.Scope,
|
|
169
194
|
binding: CapturedFeatureBinding<Summary, ROut, DirectRequires>,
|
|
170
195
|
handlers: CapturedFeatureMountHandlers<
|
|
171
196
|
FeatureSummaryMountProps<Summary>,
|
|
@@ -176,58 +201,52 @@ export const makeCapturedAppRuntime = <
|
|
|
176
201
|
FeatureSummaryCompositionIdentity<Summary>
|
|
177
202
|
>,
|
|
178
203
|
): (() => void) => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
hostContext,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}).pipe(Effect.provideService(Bus, bus))
|
|
212
|
-
const merged = Context.merge(hostContext, context)
|
|
213
|
-
const compositionService = Option.getOrThrow(
|
|
214
|
-
Context.getOption(merged, binding.composition.tag),
|
|
215
|
-
)
|
|
216
|
-
const rooted = Context.add(merged, binding.composition.tag, compositionService)
|
|
217
|
-
yield* Effect.sync(() => handlers.onLive(makeChildRuntime(rooted)))
|
|
218
|
-
}),
|
|
204
|
+
const mountInto = (scope: Scope.CloseableScope) =>
|
|
205
|
+
Effect.flatMap(binding.load, (loaded) => {
|
|
206
|
+
if (
|
|
207
|
+
!hasFeatureRequirements<
|
|
208
|
+
HostServices,
|
|
209
|
+
FeatureSummaryOpenServices<Summary>,
|
|
210
|
+
DirectRequires
|
|
211
|
+
>(hostContext, loaded.requires)
|
|
212
|
+
) {
|
|
213
|
+
return missingHostServices(binding.manifest.name)
|
|
214
|
+
}
|
|
215
|
+
const input = loaded.usesInput ? binding.parseInput(handlers.props) : Option.some(undefined)
|
|
216
|
+
return Option.match(input, {
|
|
217
|
+
onNone: () => invalidMountProps(binding.manifest.name),
|
|
218
|
+
onSome: (props) =>
|
|
219
|
+
Effect.gen(function* () {
|
|
220
|
+
const bus = Context.get(hostContext, Bus)
|
|
221
|
+
const featureContext = Context.add(hostContext, FeatureInput, props)
|
|
222
|
+
const context = yield* Layer.build(
|
|
223
|
+
Layer.provide(loaded.layer, Layer.succeedContext(featureContext)),
|
|
224
|
+
)
|
|
225
|
+
yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
|
|
226
|
+
discard: true,
|
|
227
|
+
}).pipe(Effect.provideService(Bus, bus))
|
|
228
|
+
const merged = Context.merge(hostContext, context)
|
|
229
|
+
const compositionService = Option.getOrThrow(
|
|
230
|
+
Context.getOption(merged, binding.composition.tag),
|
|
231
|
+
)
|
|
232
|
+
const rooted = Context.add(merged, binding.composition.tag, compositionService)
|
|
233
|
+
yield* Effect.sync(() => handlers.onLive(makeChildRuntime(rooted, scope)))
|
|
234
|
+
}),
|
|
235
|
+
})
|
|
219
236
|
})
|
|
220
|
-
|
|
221
|
-
|
|
237
|
+
return startMount(mountHost, ownerScope, (scope) =>
|
|
238
|
+
forkFeatureMount(mountHost, scope, instrumented(mountInto(scope)), handlers.onFailed),
|
|
239
|
+
)
|
|
222
240
|
}
|
|
223
241
|
|
|
224
242
|
const mountAnyFeatureOnto = <HostServices>(
|
|
225
243
|
hostContext: Context.Context<HostServices>,
|
|
244
|
+
ownerScope: Scope.Scope,
|
|
226
245
|
binding: AnyFeatureBinding,
|
|
227
246
|
handlers: AnyFeatureMountHandlers,
|
|
228
247
|
): (() => void) =>
|
|
229
248
|
binding.capture((exactBinding) =>
|
|
230
|
-
mountCapturedFeatureOnto(hostContext, exactBinding, {
|
|
249
|
+
mountCapturedFeatureOnto(hostContext, ownerScope, exactBinding, {
|
|
231
250
|
props: handlers.props,
|
|
232
251
|
onLive: (childRuntime) => handlers.onLive(childRuntime),
|
|
233
252
|
onFailed: handlers.onFailed,
|
|
@@ -245,11 +264,13 @@ export const makeCapturedAppRuntime = <
|
|
|
245
264
|
): Option.Option<Service> => Context.getOption(rootContext, tag),
|
|
246
265
|
runRender,
|
|
247
266
|
dispatch,
|
|
248
|
-
mountScoped,
|
|
249
|
-
mountFeature: (binding, handlers) =>
|
|
267
|
+
mountScoped: (activation) => mountScopedOnto(rootScope, activation),
|
|
268
|
+
mountFeature: (binding, handlers) =>
|
|
269
|
+
mountFeatureOnto(rootContext, rootScope, binding, handlers),
|
|
250
270
|
mountCapturedFeature: (binding, handlers) =>
|
|
251
|
-
mountCapturedFeatureOnto(rootContext, binding, handlers),
|
|
252
|
-
mountAnyFeature: (binding, handlers) =>
|
|
271
|
+
mountCapturedFeatureOnto(rootContext, rootScope, binding, handlers),
|
|
272
|
+
mountAnyFeature: (binding, handlers) =>
|
|
273
|
+
mountAnyFeatureOnto(rootContext, rootScope, binding, handlers),
|
|
253
274
|
boot: () => {
|
|
254
275
|
if (status.disposed || status.booted) {
|
|
255
276
|
return
|
|
@@ -265,6 +286,9 @@ export const makeCapturedAppRuntime = <
|
|
|
265
286
|
}
|
|
266
287
|
status.disposed = true
|
|
267
288
|
activationDisposers.forEach((dispose) => dispose())
|
|
289
|
+
// On the default runtime: the managed runtime is going away underneath us and
|
|
290
|
+
// must not interrupt the finalizers of what it mounted.
|
|
291
|
+
Effect.runFork(Scope.close(rootScope, Exit.succeed(undefined)))
|
|
268
292
|
void runtime.dispose()
|
|
269
293
|
},
|
|
270
294
|
isDisposed: () => status.disposed,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Boolean as Bool, Effect, FiberRef, GlobalValue, MutableRef, Option } from 'effect'
|
|
2
2
|
import { isDev } from '../internal/env'
|
|
3
3
|
import { EventLoopOverflow } from '../internal/errors'
|
|
4
|
+
import { microtask } from '../internal/platform'
|
|
4
5
|
|
|
5
6
|
interface EventLimitFields {
|
|
6
7
|
readonly errorAt: number
|
|
@@ -20,7 +21,7 @@ export interface EventBudget {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
const rethrowOverflow = (error: EventLoopOverflow): void =>
|
|
23
|
-
|
|
24
|
+
microtask(() => {
|
|
24
25
|
// oxlint-disable-next-line reform-rules/no-throw -- only way to surface the halt to the host's global error handler
|
|
25
26
|
throw error
|
|
26
27
|
})
|