brustjs 0.1.38-alpha → 0.1.40-alpha
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 +34 -0
- package/example/pokedex/components/ThemeToggle.tsx +11 -3
- package/package.json +16 -8
- package/runtime/cli/build.ts +123 -26
- package/runtime/cli/dev.ts +21 -0
- package/runtime/cli/help.ts +19 -0
- package/runtime/cli/jinja-staleness.ts +55 -7
- package/runtime/cli/native-routes-emit.ts +29 -7
- package/runtime/cli/ssg.ts +257 -0
- package/runtime/dev/coordinator.ts +16 -4
- package/runtime/dev/watcher.ts +16 -5
- package/runtime/index.js +52 -52
- package/runtime/index.ts +68 -3
- package/runtime/islands/bootstrap.ts +23 -0
- package/runtime/islands/build.ts +23 -1
- package/runtime/islands/native-render.ts +16 -3
- package/runtime/md/emit.ts +544 -0
- package/runtime/md/render.ts +469 -0
- package/runtime/md/routes.ts +347 -0
- package/runtime/md/scan.ts +175 -0
- package/runtime/native/build.ts +9 -1
- package/runtime/native/index.ts +4 -1
- package/runtime/native/runtime.ts +33 -2
- package/runtime/routes.ts +13 -0
- package/runtime/store/signal.ts +40 -3
package/runtime/store/signal.ts
CHANGED
|
@@ -147,18 +147,41 @@ export function computed<T>(fn: () => T): Computed<T> {
|
|
|
147
147
|
return read
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
// `fn` may return a cleanup function (React `useEffect` semantics): it runs once
|
|
151
|
+
// before each re-run, and once when the effect is disposed. Cleanups run UNTRACKED
|
|
152
|
+
// (activeConsumer nulled) so a signal read inside a cleanup never registers a spurious
|
|
153
|
+
// dependency. A `void` return is unchanged — the existing no-cleanup path.
|
|
154
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: `void | Destructor` is the React useEffect return shape — a callback with no `return` infers `void`, so swapping to `undefined` would type-error every cleanup-less caller.
|
|
155
|
+
export function effect(fn: () => void | (() => void)): () => void {
|
|
156
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: holds `fn()`'s `void | (() => void)` result; `undefined` here would reject a `void` assignment.
|
|
157
|
+
let cleanup: void | (() => void)
|
|
158
|
+
// Run the pending cleanup with dependency tracking suspended.
|
|
159
|
+
const runCleanup = () => {
|
|
160
|
+
if (typeof cleanup !== 'function') return
|
|
161
|
+
const c = cleanup
|
|
162
|
+
cleanup = undefined
|
|
163
|
+
const prev = ctx.activeConsumer
|
|
164
|
+
ctx.activeConsumer = null
|
|
165
|
+
try {
|
|
166
|
+
c()
|
|
167
|
+
} catch (e) {
|
|
168
|
+
console.error('[brust] effect cleanup threw:', e)
|
|
169
|
+
} finally {
|
|
170
|
+
ctx.activeConsumer = prev
|
|
171
|
+
}
|
|
172
|
+
}
|
|
151
173
|
const self: Consumer = {
|
|
152
174
|
deps: new Set(),
|
|
153
175
|
running: false,
|
|
154
176
|
run() {
|
|
155
177
|
if (self.running) return
|
|
156
178
|
self.running = true
|
|
179
|
+
runCleanup() // previous run's cleanup fires before the new run
|
|
157
180
|
clearDeps(self)
|
|
158
181
|
const prev = ctx.activeConsumer
|
|
159
182
|
ctx.activeConsumer = self
|
|
160
183
|
try {
|
|
161
|
-
fn()
|
|
184
|
+
cleanup = fn()
|
|
162
185
|
} finally {
|
|
163
186
|
ctx.activeConsumer = prev
|
|
164
187
|
self.running = false
|
|
@@ -166,5 +189,19 @@ export function effect(fn: () => void): () => void {
|
|
|
166
189
|
},
|
|
167
190
|
}
|
|
168
191
|
self.run()
|
|
169
|
-
return () =>
|
|
192
|
+
return () => {
|
|
193
|
+
// Guard the dispose path with the same re-entrancy flag as run(): a cleanup
|
|
194
|
+
// that writes a signal this effect still depends on (clearDeps runs AFTER
|
|
195
|
+
// runCleanup) would otherwise synchronously re-notify and re-run the body of
|
|
196
|
+
// an already-disposed effect. The flag drops that re-entrant run; a second
|
|
197
|
+
// dispose() is then a no-op (cleanup already consumed, deps already cleared).
|
|
198
|
+
if (self.running) return
|
|
199
|
+
self.running = true
|
|
200
|
+
try {
|
|
201
|
+
runCleanup() // final cleanup on dispose
|
|
202
|
+
clearDeps(self)
|
|
203
|
+
} finally {
|
|
204
|
+
self.running = false
|
|
205
|
+
}
|
|
206
|
+
}
|
|
170
207
|
}
|