effect 3.19.19 → 3.20.0

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.
Files changed (47) hide show
  1. package/dist/cjs/Data.js.map +1 -1
  2. package/dist/cjs/ParseResult.js +4 -5
  3. package/dist/cjs/ParseResult.js.map +1 -1
  4. package/dist/cjs/Scheduler.js +78 -72
  5. package/dist/cjs/Scheduler.js.map +1 -1
  6. package/dist/cjs/SchemaAST.js +4 -0
  7. package/dist/cjs/SchemaAST.js.map +1 -1
  8. package/dist/cjs/internal/effect/circular.js +2 -2
  9. package/dist/cjs/internal/effect/circular.js.map +1 -1
  10. package/dist/cjs/internal/fiberRuntime.js +4 -4
  11. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  12. package/dist/cjs/internal/version.js +1 -1
  13. package/dist/cjs/internal/version.js.map +1 -1
  14. package/dist/dts/Cron.d.ts +1 -1
  15. package/dist/dts/Data.d.ts +11 -11
  16. package/dist/dts/Data.d.ts.map +1 -1
  17. package/dist/dts/Graph.d.ts +1 -1
  18. package/dist/dts/ParseResult.d.ts +1 -1
  19. package/dist/dts/ParseResult.d.ts.map +1 -1
  20. package/dist/dts/Scheduler.d.ts +22 -19
  21. package/dist/dts/Scheduler.d.ts.map +1 -1
  22. package/dist/dts/SchemaAST.d.ts.map +1 -1
  23. package/dist/dts/Types.d.ts +7 -0
  24. package/dist/dts/Types.d.ts.map +1 -1
  25. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  26. package/dist/esm/Data.js.map +1 -1
  27. package/dist/esm/ParseResult.js +4 -5
  28. package/dist/esm/ParseResult.js.map +1 -1
  29. package/dist/esm/Scheduler.js +76 -71
  30. package/dist/esm/Scheduler.js.map +1 -1
  31. package/dist/esm/SchemaAST.js +4 -0
  32. package/dist/esm/SchemaAST.js.map +1 -1
  33. package/dist/esm/internal/effect/circular.js +2 -2
  34. package/dist/esm/internal/effect/circular.js.map +1 -1
  35. package/dist/esm/internal/fiberRuntime.js +4 -4
  36. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  37. package/dist/esm/internal/version.js +1 -1
  38. package/dist/esm/internal/version.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/Data.ts +7 -13
  41. package/src/ParseResult.ts +4 -5
  42. package/src/Scheduler.ts +84 -75
  43. package/src/SchemaAST.ts +4 -0
  44. package/src/Types.ts +8 -0
  45. package/src/internal/effect/circular.ts +13 -9
  46. package/src/internal/fiberRuntime.ts +26 -13
  47. package/src/internal/version.ts +1 -1
@@ -1071,15 +1071,15 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
1071
1071
  // handle post rest elements
1072
1072
  // ---------------------------------------------
1073
1073
  for (let j = 0; j < tail.length; j++) {
1074
- i += j
1075
- if (len < i + 1) {
1074
+ const index = i + j
1075
+ if (len < index + 1) {
1076
1076
  continue
1077
1077
  } else {
1078
- const te = tail[j](input[i], options)
1078
+ const te = tail[j](input[index], options)
1079
1079
  if (isEither(te)) {
1080
1080
  if (Either.isLeft(te)) {
1081
1081
  // the input element is present but is not valid
1082
- const e = new Pointer(i, input, te.left)
1082
+ const e = new Pointer(index, input, te.left)
1083
1083
  if (allErrors) {
1084
1084
  es.push([stepKey++, e])
1085
1085
  continue
@@ -1090,7 +1090,6 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
1090
1090
  output.push([stepKey++, te.right])
1091
1091
  } else {
1092
1092
  const nk = stepKey++
1093
- const index = i
1094
1093
  if (!queue) {
1095
1094
  queue = []
1096
1095
  }
package/src/Scheduler.ts CHANGED
@@ -21,7 +21,69 @@ export type Task = () => void
21
21
  */
22
22
  export interface Scheduler {
23
23
  shouldYield(fiber: RuntimeFiber<unknown, unknown>): number | false
24
- scheduleTask(task: Task, priority: number): void
24
+ scheduleTask(task: Task, priority: number, fiber?: RuntimeFiber<unknown, unknown>): void
25
+ }
26
+
27
+ /**
28
+ * @since 3.20.0
29
+ * @category models
30
+ */
31
+ export class SchedulerRunner {
32
+ running = false
33
+ tasks = new PriorityBuckets()
34
+
35
+ constructor(
36
+ readonly scheduleDrain: (depth: number, drain: (depth: number) => void) => void
37
+ ) {}
38
+
39
+ private starveInternal = (depth: number) => {
40
+ const tasks = this.tasks.buckets
41
+ this.tasks.buckets = []
42
+ for (const [_, toRun] of tasks) {
43
+ for (let i = 0; i < toRun.length; i++) {
44
+ toRun[i]()
45
+ }
46
+ }
47
+ if (this.tasks.buckets.length === 0) {
48
+ this.running = false
49
+ } else {
50
+ this.starve(depth)
51
+ }
52
+ }
53
+
54
+ private starve(depth = 0) {
55
+ this.scheduleDrain(depth, this.starveInternal)
56
+ }
57
+
58
+ scheduleTask(task: Task, priority: number) {
59
+ this.tasks.scheduleTask(task, priority)
60
+ if (!this.running) {
61
+ this.running = true
62
+ this.starve()
63
+ }
64
+ }
65
+ /**
66
+ * @since 3.20.0
67
+ * @category constructors
68
+ */
69
+ static cached(
70
+ scheduleDrain: (depth: number, drain: (depth: number) => void) => void
71
+ ) {
72
+ const fallback = new SchedulerRunner(scheduleDrain)
73
+ const runners = new WeakMap<RuntimeFiber<unknown, unknown>, SchedulerRunner>()
74
+
75
+ return (fiber?: RuntimeFiber<unknown, unknown>) => {
76
+ if (fiber === undefined) {
77
+ return fallback
78
+ }
79
+ let runner = runners.get(fiber)
80
+ if (runner === undefined) {
81
+ runner = new SchedulerRunner(scheduleDrain)
82
+ runners.set(fiber, runner)
83
+ }
84
+ return runner
85
+ }
86
+ }
25
87
  }
26
88
 
27
89
  /**
@@ -62,14 +124,13 @@ export class PriorityBuckets<in out T = Task> {
62
124
  * @category constructors
63
125
  */
64
126
  export class MixedScheduler implements Scheduler {
65
- /**
66
- * @since 2.0.0
67
- */
68
- running = false
69
- /**
70
- * @since 2.0.0
71
- */
72
- tasks = new PriorityBuckets()
127
+ private readonly getRunner = SchedulerRunner.cached((depth, drain) => {
128
+ if (depth >= this.maxNextTickBeforeTimer) {
129
+ setTimeout(() => drain(0), 0)
130
+ } else {
131
+ Promise.resolve(void 0).then(() => drain(depth + 1))
132
+ }
133
+ })
73
134
 
74
135
  constructor(
75
136
  /**
@@ -78,35 +139,6 @@ export class MixedScheduler implements Scheduler {
78
139
  readonly maxNextTickBeforeTimer: number
79
140
  ) {}
80
141
 
81
- /**
82
- * @since 2.0.0
83
- */
84
- private starveInternal(depth: number) {
85
- const tasks = this.tasks.buckets
86
- this.tasks.buckets = []
87
- for (const [_, toRun] of tasks) {
88
- for (let i = 0; i < toRun.length; i++) {
89
- toRun[i]()
90
- }
91
- }
92
- if (this.tasks.buckets.length === 0) {
93
- this.running = false
94
- } else {
95
- this.starve(depth)
96
- }
97
- }
98
-
99
- /**
100
- * @since 2.0.0
101
- */
102
- private starve(depth = 0) {
103
- if (depth >= this.maxNextTickBeforeTimer) {
104
- setTimeout(() => this.starveInternal(0), 0)
105
- } else {
106
- Promise.resolve(void 0).then(() => this.starveInternal(depth + 1))
107
- }
108
- }
109
-
110
142
  /**
111
143
  * @since 2.0.0
112
144
  */
@@ -119,12 +151,8 @@ export class MixedScheduler implements Scheduler {
119
151
  /**
120
152
  * @since 2.0.0
121
153
  */
122
- scheduleTask(task: Task, priority: number) {
123
- this.tasks.scheduleTask(task, priority)
124
- if (!this.running) {
125
- this.running = true
126
- this.starve()
127
- }
154
+ scheduleTask(task: Task, priority: number, fiber?: RuntimeFiber<unknown, unknown>) {
155
+ this.getRunner(fiber).scheduleTask(task, priority)
128
156
  }
129
157
  }
130
158
 
@@ -155,9 +183,9 @@ export class SyncScheduler implements Scheduler {
155
183
  /**
156
184
  * @since 2.0.0
157
185
  */
158
- scheduleTask(task: Task, priority: number) {
186
+ scheduleTask(task: Task, priority: number, fiber?: RuntimeFiber<unknown, unknown>) {
159
187
  if (this.deferred) {
160
- defaultScheduler.scheduleTask(task, priority)
188
+ defaultScheduler.scheduleTask(task, priority, fiber)
161
189
  } else {
162
190
  this.tasks.scheduleTask(task, priority)
163
191
  }
@@ -207,9 +235,9 @@ export class ControlledScheduler implements Scheduler {
207
235
  /**
208
236
  * @since 2.0.0
209
237
  */
210
- scheduleTask(task: Task, priority: number) {
238
+ scheduleTask(task: Task, priority: number, fiber?: RuntimeFiber<unknown, unknown>) {
211
239
  if (this.deferred) {
212
- defaultScheduler.scheduleTask(task, priority)
240
+ defaultScheduler.scheduleTask(task, priority, fiber)
213
241
  } else {
214
242
  this.tasks.scheduleTask(task, priority)
215
243
  }
@@ -254,16 +282,16 @@ export const makeMatrix = (...record: Array<[number, Scheduler]>): Scheduler =>
254
282
  }
255
283
  return false
256
284
  },
257
- scheduleTask(task, priority) {
285
+ scheduleTask(task, priority, fiber) {
258
286
  let scheduler: Scheduler | undefined = undefined
259
287
  for (const i of index) {
260
288
  if (priority >= i[0]) {
261
289
  scheduler = i[1]
262
290
  } else {
263
- return (scheduler ?? defaultScheduler).scheduleTask(task, priority)
291
+ return (scheduler ?? defaultScheduler).scheduleTask(task, priority, fiber)
264
292
  }
265
293
  }
266
- return (scheduler ?? defaultScheduler).scheduleTask(task, priority)
294
+ return (scheduler ?? defaultScheduler).scheduleTask(task, priority, fiber)
267
295
  }
268
296
  }
269
297
  }
@@ -298,31 +326,12 @@ export const makeBatched = (
298
326
  callback: (runBatch: () => void) => void,
299
327
  shouldYield: Scheduler["shouldYield"] = defaultShouldYield
300
328
  ) => {
301
- let running = false
302
- const tasks = new PriorityBuckets()
303
- const starveInternal = () => {
304
- const tasksToRun = tasks.buckets
305
- tasks.buckets = []
306
- for (const [_, toRun] of tasksToRun) {
307
- for (let i = 0; i < toRun.length; i++) {
308
- toRun[i]()
309
- }
310
- }
311
- if (tasks.buckets.length === 0) {
312
- running = false
313
- } else {
314
- starve()
315
- }
316
- }
317
-
318
- const starve = () => callback(starveInternal)
329
+ const getRunner = SchedulerRunner.cached((_, drain) => {
330
+ callback(() => drain(0))
331
+ })
319
332
 
320
- return make((task, priority) => {
321
- tasks.scheduleTask(task, priority)
322
- if (!running) {
323
- running = true
324
- starve()
325
- }
333
+ return make((task, priority, fiber) => {
334
+ getRunner(fiber).scheduleTask(task, priority)
326
335
  }, shouldYield)
327
336
  }
328
337
 
package/src/SchemaAST.ts CHANGED
@@ -2239,6 +2239,8 @@ const getIndexSignatures = (ast: AST): Array<IndexSignature> => {
2239
2239
  return getIndexSignatures(ast.f())
2240
2240
  case "Refinement":
2241
2241
  return getIndexSignatures(ast.from)
2242
+ case "Transformation":
2243
+ return getIndexSignatures(ast.to)
2242
2244
  }
2243
2245
  return []
2244
2246
  }
@@ -2336,6 +2338,8 @@ export const getPropertyKeyIndexedAccess = (ast: AST, name: PropertyKey): Proper
2336
2338
  return getPropertyKeyIndexedAccess(ast.f(), name)
2337
2339
  case "Refinement":
2338
2340
  return getPropertyKeyIndexedAccess(ast.from, name)
2341
+ case "Transformation":
2342
+ return getPropertyKeyIndexedAccess(ast.to, name)
2339
2343
  }
2340
2344
  throw new Error(errors_.getASTUnsupportedSchemaErrorMessage(ast))
2341
2345
  }
package/src/Types.ts CHANGED
@@ -351,3 +351,11 @@ export type NoExcessProperties<T, U> = T & { readonly [K in Exclude<keyof U, key
351
351
  * @since 3.15.0
352
352
  */
353
353
  export type Ctor<T = {}> = new(...args: Array<any>) => T
354
+
355
+ /**
356
+ * Conditional type that returns `void` if `S` is an empty object type,
357
+ * otherwise returns `S`.
358
+ *
359
+ * @since 3.19.20
360
+ */
361
+ export type VoidIfEmpty<S> = keyof S extends never ? void : S
@@ -70,14 +70,18 @@ class Semaphore {
70
70
  updateTakenUnsafe(fiber: Fiber.RuntimeFiber<any, any>, f: (n: number) => number): Effect.Effect<number> {
71
71
  this.taken = f(this.taken)
72
72
  if (this.waiters.size > 0) {
73
- fiber.getFiberRef(currentScheduler).scheduleTask(() => {
74
- const iter = this.waiters.values()
75
- let item = iter.next()
76
- while (item.done === false && this.free > 0) {
77
- item.value()
78
- item = iter.next()
79
- }
80
- }, fiber.getFiberRef(core.currentSchedulingPriority))
73
+ fiber.getFiberRef(currentScheduler).scheduleTask(
74
+ () => {
75
+ const iter = this.waiters.values()
76
+ let item = iter.next()
77
+ while (item.done === false && this.free > 0) {
78
+ item.value()
79
+ item = iter.next()
80
+ }
81
+ },
82
+ fiber.getFiberRef(core.currentSchedulingPriority),
83
+ fiber
84
+ )
81
85
  }
82
86
  return core.succeed(this.free)
83
87
  }
@@ -143,7 +147,7 @@ class Latch extends Effectable.Class<void> implements Effect.Latch {
143
147
  return core.void
144
148
  }
145
149
  this.scheduled = true
146
- fiber.currentScheduler.scheduleTask(this.flushWaiters, fiber.getFiberRef(core.currentSchedulingPriority))
150
+ fiber.currentScheduler.scheduleTask(this.flushWaiters, fiber.getFiberRef(core.currentSchedulingPriority), fiber)
147
151
  return core.void
148
152
  }
149
153
  private flushWaiters = () => {
@@ -708,7 +708,8 @@ export class FiberRuntime<in out A, in out E = never> extends Effectable.Class<A
708
708
  drainQueueLaterOnExecutor() {
709
709
  this.currentScheduler.scheduleTask(
710
710
  this.run,
711
- this.getFiberRef(core.currentSchedulingPriority)
711
+ this.getFiberRef(core.currentSchedulingPriority),
712
+ this
712
713
  )
713
714
  }
714
715
 
@@ -2209,9 +2210,13 @@ export const forEachConcurrentDiscard = <A, X, E, R>(
2209
2210
  const results = new Array()
2210
2211
  const interruptAll = () =>
2211
2212
  fibers.forEach((fiber) => {
2212
- fiber.currentScheduler.scheduleTask(() => {
2213
- fiber.unsafeInterruptAsFork(parent.id())
2214
- }, 0)
2213
+ fiber.currentScheduler.scheduleTask(
2214
+ () => {
2215
+ fiber.unsafeInterruptAsFork(parent.id())
2216
+ },
2217
+ 0,
2218
+ fiber
2219
+ )
2215
2220
  })
2216
2221
  const startOrder = new Array<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
2217
2222
  const joinOrder = new Array<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
@@ -2234,12 +2239,16 @@ export const forEachConcurrentDiscard = <A, X, E, R>(
2234
2239
  parent.currentRuntimeFlags,
2235
2240
  fiberScope.globalScope
2236
2241
  )
2237
- parent.currentScheduler.scheduleTask(() => {
2238
- if (interruptImmediately) {
2239
- fiber.unsafeInterruptAsFork(parent.id())
2240
- }
2241
- fiber.resume(runnable)
2242
- }, 0)
2242
+ parent.currentScheduler.scheduleTask(
2243
+ () => {
2244
+ if (interruptImmediately) {
2245
+ fiber.unsafeInterruptAsFork(parent.id())
2246
+ }
2247
+ fiber.resume(runnable)
2248
+ },
2249
+ 0,
2250
+ fiber
2251
+ )
2243
2252
  return fiber
2244
2253
  }
2245
2254
  const onInterruptSignal = () => {
@@ -2295,9 +2304,13 @@ export const forEachConcurrentDiscard = <A, X, E, R>(
2295
2304
  startOrder.push(fiber)
2296
2305
  fibers.add(fiber)
2297
2306
  if (interrupted) {
2298
- fiber.currentScheduler.scheduleTask(() => {
2299
- fiber.unsafeInterruptAsFork(parent.id())
2300
- }, 0)
2307
+ fiber.currentScheduler.scheduleTask(
2308
+ () => {
2309
+ fiber.unsafeInterruptAsFork(parent.id())
2310
+ },
2311
+ 0,
2312
+ fiber
2313
+ )
2301
2314
  }
2302
2315
  fiber.addObserver((wrapped) => {
2303
2316
  let exit: Exit.Exit<any, any> | core.Blocked
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.19.19"
1
+ let moduleVersion = "3.20.0"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4