tutuca 0.9.92 → 0.9.94

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.
@@ -2920,36 +2920,81 @@ class Transactor {
2920
2920
  this.transactions = [];
2921
2921
  this.state = new State(rootValue);
2922
2922
  this.onTransactionPushed = () => {};
2923
+ this._inflight = new Set;
2923
2924
  }
2924
2925
  pushTransaction(t) {
2925
2926
  this.transactions.push(t);
2926
2927
  this.onTransactionPushed(t);
2927
2928
  }
2929
+ _link(child, parent) {
2930
+ if (parent) {
2931
+ const release = parent.completion.track();
2932
+ child.completion.whenSubtreeSettled().then(release);
2933
+ }
2934
+ return child;
2935
+ }
2928
2936
  pushSend(path, name, args = [], opts = {}, parent = null) {
2929
- this.pushTransaction(new SendEvent(path, this, name, args, parent, opts));
2937
+ const t = new SendEvent(path, this, name, args, parent, opts);
2938
+ this.pushTransaction(t);
2939
+ return this._link(t, parent);
2940
+ }
2941
+ pushInput(path, name, args = [], opts = {}, parent = null) {
2942
+ const t = new InputDispatchEvent(path, this, name, args, parent, opts);
2943
+ this.pushTransaction(t);
2944
+ return this._link(t, parent);
2930
2945
  }
2931
2946
  pushBubble(path, name, args = [], opts = {}, parent = null, targetPath = null) {
2932
2947
  const newOpts = opts.skipSelf ? { ...opts, skipSelf: false } : opts;
2933
- this.pushTransaction(new BubbleEvent(path, this, name, args, parent, newOpts, targetPath));
2948
+ const t = new BubbleEvent(path, this, name, args, parent, newOpts, targetPath);
2949
+ this.pushTransaction(t);
2950
+ return this._link(t, parent);
2951
+ }
2952
+ pushRequest(path, name, args = [], opts = {}, parent = null) {
2953
+ const release = parent ? parent.completion.track() : null;
2954
+ const p = this._runRequest(path, name, args, opts, parent, release);
2955
+ this._inflight.add(p);
2956
+ p.finally(() => this._inflight.delete(p));
2957
+ return p;
2958
+ }
2959
+ async settle(maxTurns = 1e4) {
2960
+ while ((this.hasPendingTransactions || this._inflight.size) && maxTurns-- > 0) {
2961
+ while (this.hasPendingTransactions)
2962
+ this.transactNext();
2963
+ if (this._inflight.size)
2964
+ await Promise.allSettled([...this._inflight]);
2965
+ }
2934
2966
  }
2935
- async pushRequest(path, name, args = [], opts = {}, parent = null) {
2936
- const curRoot = this.state.val;
2937
- const txnPath = path.toTransactionPath();
2938
- const curLeaf = txnPath.lookup(curRoot);
2939
- const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
2940
- const reqCtx = new RequestContext(path, this, parent, curRoot);
2941
- const resHandlerName = opts?.onResName ?? name;
2942
- const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
2943
- const push = (specificName, baseName, singleArg, result, error) => {
2944
- const resArgs = specificName ? [singleArg] : [result, error];
2945
- const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
2946
- this.pushTransaction(t);
2967
+ async _runRequest(path, name, args = [], opts = {}, parent = null, release = null) {
2968
+ let released = false;
2969
+ const transfer = (t) => {
2970
+ if (release) {
2971
+ released = true;
2972
+ t.completion.whenSubtreeSettled().then(release);
2973
+ }
2947
2974
  };
2948
2975
  try {
2949
- const result = await handler.fn.apply(null, [...args, reqCtx]);
2950
- push(opts?.onOkName, resHandlerName, result, result, null);
2951
- } catch (error) {
2952
- push(opts?.onErrorName, resHandlerName, error, null, error);
2976
+ const curRoot = this.state.val;
2977
+ const txnPath = path.toTransactionPath();
2978
+ const curLeaf = txnPath.lookup(curRoot);
2979
+ const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
2980
+ const reqCtx = new RequestContext(path, this, parent, curRoot);
2981
+ const resHandlerName = opts?.onResName ?? name;
2982
+ const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
2983
+ const push = (specificName, baseName, singleArg, result, error) => {
2984
+ const resArgs = specificName ? [singleArg] : [result, error];
2985
+ const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
2986
+ transfer(t);
2987
+ this.pushTransaction(t);
2988
+ };
2989
+ try {
2990
+ const result = await handler.fn.apply(null, [...args, reqCtx]);
2991
+ push(opts?.onOkName, resHandlerName, result, result, null);
2992
+ } catch (error) {
2993
+ push(opts?.onErrorName, resHandlerName, error, null, error);
2994
+ }
2995
+ } finally {
2996
+ if (release && !released)
2997
+ release();
2953
2998
  }
2954
2999
  }
2955
3000
  get hasPendingTransactions() {
@@ -2960,13 +3005,18 @@ class Transactor {
2960
3005
  this.transact(this.transactions.shift());
2961
3006
  }
2962
3007
  transact(transaction) {
2963
- const curState = this.state.val;
2964
- const newState = transaction.run(curState, this.comps);
2965
- if (newState !== undefined) {
2966
- this.state.set(newState, { transaction });
2967
- transaction.afterTransaction();
2968
- } else
2969
- console.warn("undefined new state", { curState, transaction });
3008
+ try {
3009
+ const curState = this.state.val;
3010
+ const newState = transaction.run(curState, this.comps);
3011
+ if (newState !== undefined) {
3012
+ this.state.set(newState, { transaction });
3013
+ transaction.afterTransaction();
3014
+ } else
3015
+ console.warn("undefined new state", { curState, transaction });
3016
+ } finally {
3017
+ transaction._completion?.ensureSelfSettled();
3018
+ transaction._completion?.releaseSelf();
3019
+ }
2970
3020
  }
2971
3021
  transactInputNow(path, event, eventHandler, dragInfo) {
2972
3022
  this.transact(new InputEvent(path, event, eventHandler, this, dragInfo));
@@ -2987,18 +3037,17 @@ class Transaction {
2987
3037
  this.path = path;
2988
3038
  this.transactor = transactor;
2989
3039
  this.parentTransaction = parentTransaction;
2990
- this._task = null;
3040
+ this._completion = null;
2991
3041
  }
2992
- get task() {
2993
- this._task ??= new Task;
2994
- return this._task;
3042
+ get completion() {
3043
+ this._completion ??= new Completion;
3044
+ return this._completion;
2995
3045
  }
2996
- getCompletionPromise() {
2997
- return this.task.promise;
3046
+ whenSettled() {
3047
+ return this.completion.whenSettled();
2998
3048
  }
2999
- setParent(parentTransaction) {
3000
- this.parentTransaction = parentTransaction;
3001
- parentTransaction.task.addDep(this.task);
3049
+ whenSubtreeSettled() {
3050
+ return this.completion.whenSubtreeSettled();
3002
3051
  }
3003
3052
  run(rootValue, comps) {
3004
3053
  return this.updateRootValue(rootValue, comps);
@@ -3024,7 +3073,7 @@ class Transaction {
3024
3073
  const txnPath = this.getTransactionPath();
3025
3074
  const curLeaf = txnPath.lookup(curRoot);
3026
3075
  const newLeaf = this.callHandler(curRoot, curLeaf, comps);
3027
- this._task?.complete?.({ value: newLeaf, old: curLeaf });
3076
+ this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
3028
3077
  return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
3029
3078
  }
3030
3079
  lookupName(_name) {
@@ -3161,29 +3210,69 @@ class BubbleEvent extends SendEvent {
3161
3210
  }
3162
3211
  }
3163
3212
 
3164
- class Task {
3213
+ class InputDispatchEvent extends NameArgsTransaction {
3214
+ handlerProp = "input";
3215
+ }
3216
+
3217
+ class Completion {
3165
3218
  constructor() {
3166
- this.deps = [];
3167
- this.val = this.resolve = this.reject = null;
3168
- this.promise = new Promise((res, rej) => {
3169
- this.resolve = res;
3170
- this.reject = rej;
3219
+ this.val = undefined;
3220
+ this.selfSettled = false;
3221
+ this.subtreeSettled = false;
3222
+ this.pending = 1;
3223
+ this._selfResolve = null;
3224
+ this._selfPromise = null;
3225
+ this._subtreeResolve = null;
3226
+ this._subtreePromise = null;
3227
+ this._selfReleased = false;
3228
+ }
3229
+ whenSettled() {
3230
+ if (this.selfSettled)
3231
+ return Promise.resolve(this.val);
3232
+ this._selfPromise ??= new Promise((res) => {
3233
+ this._selfResolve = res;
3171
3234
  });
3172
- this.isCompleted = false;
3235
+ return this._selfPromise;
3173
3236
  }
3174
- addDep(task) {
3175
- console.assert(!this.isCompleted, "addDep for completed task", this, task);
3176
- this.deps.push(task);
3177
- task.promise.then((_) => this._check());
3237
+ whenSubtreeSettled() {
3238
+ if (this.subtreeSettled)
3239
+ return Promise.resolve(this.val);
3240
+ this._subtreePromise ??= new Promise((res) => {
3241
+ this._subtreeResolve = res;
3242
+ });
3243
+ return this._subtreePromise;
3178
3244
  }
3179
- complete(val) {
3245
+ markSelfSettled(val) {
3246
+ if (this.selfSettled)
3247
+ return;
3248
+ this.selfSettled = true;
3180
3249
  this.val = val;
3181
- this._check();
3250
+ this._selfResolve?.(val);
3251
+ }
3252
+ ensureSelfSettled() {
3253
+ if (!this.selfSettled)
3254
+ this.markSelfSettled(this.val);
3182
3255
  }
3183
- _check() {
3184
- if (this.deps.every((task) => task.isCompleted)) {
3185
- this.isCompleted = true;
3186
- this.resolve(this);
3256
+ track() {
3257
+ this.pending++;
3258
+ let done = false;
3259
+ return () => {
3260
+ if (done)
3261
+ return;
3262
+ done = true;
3263
+ this._release();
3264
+ };
3265
+ }
3266
+ releaseSelf() {
3267
+ if (this._selfReleased)
3268
+ return;
3269
+ this._selfReleased = true;
3270
+ this._release();
3271
+ }
3272
+ _release() {
3273
+ if (--this.pending === 0) {
3274
+ this.subtreeSettled = true;
3275
+ this._subtreeResolve?.(this.val);
3187
3276
  }
3188
3277
  }
3189
3278
  }
@@ -3222,6 +3311,9 @@ class Dispatcher {
3222
3311
  requestAtPath(path, name, args, opts) {
3223
3312
  return this.transactor.pushRequest(path, name, args, opts, this.parent);
3224
3313
  }
3314
+ inputAtPath(path, name, args, opts) {
3315
+ return this.transactor.pushInput(path, name, args, opts, this.parent);
3316
+ }
3225
3317
  lookupTypeFor(name, inst) {
3226
3318
  return this.transactor.comps.getCompFor(inst).scope.lookupComponent(name);
3227
3319
  }
@@ -3645,6 +3737,45 @@ import {
3645
3737
  version
3646
3738
  } from "immutable";
3647
3739
 
3740
+ // src/on.js
3741
+ var OP_KINDS = ["send", "bubble", "request", "input"];
3742
+ function phaseOps(phase) {
3743
+ const ops = [];
3744
+ for (const type of OP_KINDS)
3745
+ for (const a of phase[type] ?? [])
3746
+ ops.push({ type, ...a });
3747
+ for (const a of phase.do ?? [])
3748
+ ops.push(a);
3749
+ return ops;
3750
+ }
3751
+ function resolveArgs(args, self) {
3752
+ return typeof args === "function" ? args(self) ?? [] : args ?? [];
3753
+ }
3754
+ function dispatchPhase(dispatcher, targetPath, phase, self) {
3755
+ if (!phase)
3756
+ return;
3757
+ for (const op of phaseOps(phase)) {
3758
+ const args = resolveArgs(op.args, self);
3759
+ switch (op.type) {
3760
+ case "send":
3761
+ dispatcher.sendAtPath(targetPath, op.name, args, op.opts);
3762
+ break;
3763
+ case "bubble":
3764
+ dispatcher.sendAtPath(targetPath, op.name, args, {
3765
+ skipSelf: true,
3766
+ bubbles: true,
3767
+ ...op.opts
3768
+ });
3769
+ break;
3770
+ case "request":
3771
+ dispatcher.requestAtPath(targetPath, op.name, args, op.opts);
3772
+ break;
3773
+ case "input":
3774
+ dispatcher.inputAtPath(targetPath, op.name, args, op.opts);
3775
+ break;
3776
+ }
3777
+ }
3778
+ }
3648
3779
  // src/oo.js
3649
3780
  import { Map as IMap, Set as ISet, List, OrderedMap, Record } from "immutable";
3650
3781
  var BAD_VALUE = Symbol("BadValue");
@@ -4072,8 +4203,10 @@ export {
4072
4203
  test,
4073
4204
  setIn,
4074
4205
  set,
4206
+ resolveArgs,
4075
4207
  removeIn,
4076
4208
  remove,
4209
+ phaseOps,
4077
4210
  mergeWith,
4078
4211
  mergeDeepWith,
4079
4212
  mergeDeep,
@@ -4106,6 +4239,7 @@ export {
4106
4239
  getIn,
4107
4240
  get,
4108
4241
  fromJS,
4242
+ dispatchPhase,
4109
4243
  css,
4110
4244
  component,
4111
4245
  compileClassesToStyleText,
@@ -7290,36 +7290,81 @@ class Transactor {
7290
7290
  this.transactions = [];
7291
7291
  this.state = new State(rootValue);
7292
7292
  this.onTransactionPushed = () => {};
7293
+ this._inflight = new Set;
7293
7294
  }
7294
7295
  pushTransaction(t) {
7295
7296
  this.transactions.push(t);
7296
7297
  this.onTransactionPushed(t);
7297
7298
  }
7299
+ _link(child, parent) {
7300
+ if (parent) {
7301
+ const release = parent.completion.track();
7302
+ child.completion.whenSubtreeSettled().then(release);
7303
+ }
7304
+ return child;
7305
+ }
7298
7306
  pushSend(path, name, args = [], opts = {}, parent = null) {
7299
- this.pushTransaction(new SendEvent(path, this, name, args, parent, opts));
7307
+ const t = new SendEvent(path, this, name, args, parent, opts);
7308
+ this.pushTransaction(t);
7309
+ return this._link(t, parent);
7310
+ }
7311
+ pushInput(path, name, args = [], opts = {}, parent = null) {
7312
+ const t = new InputDispatchEvent(path, this, name, args, parent, opts);
7313
+ this.pushTransaction(t);
7314
+ return this._link(t, parent);
7300
7315
  }
7301
7316
  pushBubble(path, name, args = [], opts = {}, parent = null, targetPath = null) {
7302
7317
  const newOpts = opts.skipSelf ? { ...opts, skipSelf: false } : opts;
7303
- this.pushTransaction(new BubbleEvent(path, this, name, args, parent, newOpts, targetPath));
7304
- }
7305
- async pushRequest(path, name, args = [], opts = {}, parent = null) {
7306
- const curRoot = this.state.val;
7307
- const txnPath = path.toTransactionPath();
7308
- const curLeaf = txnPath.lookup(curRoot);
7309
- const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
7310
- const reqCtx = new RequestContext(path, this, parent, curRoot);
7311
- const resHandlerName = opts?.onResName ?? name;
7312
- const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
7313
- const push = (specificName, baseName, singleArg, result, error) => {
7314
- const resArgs = specificName ? [singleArg] : [result, error];
7315
- const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
7316
- this.pushTransaction(t);
7318
+ const t = new BubbleEvent(path, this, name, args, parent, newOpts, targetPath);
7319
+ this.pushTransaction(t);
7320
+ return this._link(t, parent);
7321
+ }
7322
+ pushRequest(path, name, args = [], opts = {}, parent = null) {
7323
+ const release = parent ? parent.completion.track() : null;
7324
+ const p = this._runRequest(path, name, args, opts, parent, release);
7325
+ this._inflight.add(p);
7326
+ p.finally(() => this._inflight.delete(p));
7327
+ return p;
7328
+ }
7329
+ async settle(maxTurns = 1e4) {
7330
+ while ((this.hasPendingTransactions || this._inflight.size) && maxTurns-- > 0) {
7331
+ while (this.hasPendingTransactions)
7332
+ this.transactNext();
7333
+ if (this._inflight.size)
7334
+ await Promise.allSettled([...this._inflight]);
7335
+ }
7336
+ }
7337
+ async _runRequest(path, name, args = [], opts = {}, parent = null, release = null) {
7338
+ let released = false;
7339
+ const transfer = (t) => {
7340
+ if (release) {
7341
+ released = true;
7342
+ t.completion.whenSubtreeSettled().then(release);
7343
+ }
7317
7344
  };
7318
7345
  try {
7319
- const result = await handler.fn.apply(null, [...args, reqCtx]);
7320
- push(opts?.onOkName, resHandlerName, result, result, null);
7321
- } catch (error) {
7322
- push(opts?.onErrorName, resHandlerName, error, null, error);
7346
+ const curRoot = this.state.val;
7347
+ const txnPath = path.toTransactionPath();
7348
+ const curLeaf = txnPath.lookup(curRoot);
7349
+ const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
7350
+ const reqCtx = new RequestContext(path, this, parent, curRoot);
7351
+ const resHandlerName = opts?.onResName ?? name;
7352
+ const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
7353
+ const push = (specificName, baseName, singleArg, result, error) => {
7354
+ const resArgs = specificName ? [singleArg] : [result, error];
7355
+ const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
7356
+ transfer(t);
7357
+ this.pushTransaction(t);
7358
+ };
7359
+ try {
7360
+ const result = await handler.fn.apply(null, [...args, reqCtx]);
7361
+ push(opts?.onOkName, resHandlerName, result, result, null);
7362
+ } catch (error) {
7363
+ push(opts?.onErrorName, resHandlerName, error, null, error);
7364
+ }
7365
+ } finally {
7366
+ if (release && !released)
7367
+ release();
7323
7368
  }
7324
7369
  }
7325
7370
  get hasPendingTransactions() {
@@ -7330,13 +7375,18 @@ class Transactor {
7330
7375
  this.transact(this.transactions.shift());
7331
7376
  }
7332
7377
  transact(transaction) {
7333
- const curState = this.state.val;
7334
- const newState = transaction.run(curState, this.comps);
7335
- if (newState !== undefined) {
7336
- this.state.set(newState, { transaction });
7337
- transaction.afterTransaction();
7338
- } else
7339
- console.warn("undefined new state", { curState, transaction });
7378
+ try {
7379
+ const curState = this.state.val;
7380
+ const newState = transaction.run(curState, this.comps);
7381
+ if (newState !== undefined) {
7382
+ this.state.set(newState, { transaction });
7383
+ transaction.afterTransaction();
7384
+ } else
7385
+ console.warn("undefined new state", { curState, transaction });
7386
+ } finally {
7387
+ transaction._completion?.ensureSelfSettled();
7388
+ transaction._completion?.releaseSelf();
7389
+ }
7340
7390
  }
7341
7391
  transactInputNow(path, event, eventHandler, dragInfo) {
7342
7392
  this.transact(new InputEvent(path, event, eventHandler, this, dragInfo));
@@ -7357,18 +7407,17 @@ class Transaction {
7357
7407
  this.path = path;
7358
7408
  this.transactor = transactor;
7359
7409
  this.parentTransaction = parentTransaction;
7360
- this._task = null;
7410
+ this._completion = null;
7361
7411
  }
7362
- get task() {
7363
- this._task ??= new Task;
7364
- return this._task;
7412
+ get completion() {
7413
+ this._completion ??= new Completion;
7414
+ return this._completion;
7365
7415
  }
7366
- getCompletionPromise() {
7367
- return this.task.promise;
7416
+ whenSettled() {
7417
+ return this.completion.whenSettled();
7368
7418
  }
7369
- setParent(parentTransaction) {
7370
- this.parentTransaction = parentTransaction;
7371
- parentTransaction.task.addDep(this.task);
7419
+ whenSubtreeSettled() {
7420
+ return this.completion.whenSubtreeSettled();
7372
7421
  }
7373
7422
  run(rootValue, comps) {
7374
7423
  return this.updateRootValue(rootValue, comps);
@@ -7394,7 +7443,7 @@ class Transaction {
7394
7443
  const txnPath = this.getTransactionPath();
7395
7444
  const curLeaf = txnPath.lookup(curRoot);
7396
7445
  const newLeaf = this.callHandler(curRoot, curLeaf, comps);
7397
- this._task?.complete?.({ value: newLeaf, old: curLeaf });
7446
+ this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
7398
7447
  return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
7399
7448
  }
7400
7449
  lookupName(_name) {
@@ -7531,29 +7580,69 @@ class BubbleEvent extends SendEvent {
7531
7580
  }
7532
7581
  }
7533
7582
 
7534
- class Task {
7583
+ class InputDispatchEvent extends NameArgsTransaction {
7584
+ handlerProp = "input";
7585
+ }
7586
+
7587
+ class Completion {
7535
7588
  constructor() {
7536
- this.deps = [];
7537
- this.val = this.resolve = this.reject = null;
7538
- this.promise = new Promise((res, rej) => {
7539
- this.resolve = res;
7540
- this.reject = rej;
7589
+ this.val = undefined;
7590
+ this.selfSettled = false;
7591
+ this.subtreeSettled = false;
7592
+ this.pending = 1;
7593
+ this._selfResolve = null;
7594
+ this._selfPromise = null;
7595
+ this._subtreeResolve = null;
7596
+ this._subtreePromise = null;
7597
+ this._selfReleased = false;
7598
+ }
7599
+ whenSettled() {
7600
+ if (this.selfSettled)
7601
+ return Promise.resolve(this.val);
7602
+ this._selfPromise ??= new Promise((res) => {
7603
+ this._selfResolve = res;
7541
7604
  });
7542
- this.isCompleted = false;
7605
+ return this._selfPromise;
7543
7606
  }
7544
- addDep(task) {
7545
- console.assert(!this.isCompleted, "addDep for completed task", this, task);
7546
- this.deps.push(task);
7547
- task.promise.then((_) => this._check());
7607
+ whenSubtreeSettled() {
7608
+ if (this.subtreeSettled)
7609
+ return Promise.resolve(this.val);
7610
+ this._subtreePromise ??= new Promise((res) => {
7611
+ this._subtreeResolve = res;
7612
+ });
7613
+ return this._subtreePromise;
7548
7614
  }
7549
- complete(val) {
7615
+ markSelfSettled(val) {
7616
+ if (this.selfSettled)
7617
+ return;
7618
+ this.selfSettled = true;
7550
7619
  this.val = val;
7551
- this._check();
7620
+ this._selfResolve?.(val);
7621
+ }
7622
+ ensureSelfSettled() {
7623
+ if (!this.selfSettled)
7624
+ this.markSelfSettled(this.val);
7552
7625
  }
7553
- _check() {
7554
- if (this.deps.every((task) => task.isCompleted)) {
7555
- this.isCompleted = true;
7556
- this.resolve(this);
7626
+ track() {
7627
+ this.pending++;
7628
+ let done = false;
7629
+ return () => {
7630
+ if (done)
7631
+ return;
7632
+ done = true;
7633
+ this._release();
7634
+ };
7635
+ }
7636
+ releaseSelf() {
7637
+ if (this._selfReleased)
7638
+ return;
7639
+ this._selfReleased = true;
7640
+ this._release();
7641
+ }
7642
+ _release() {
7643
+ if (--this.pending === 0) {
7644
+ this.subtreeSettled = true;
7645
+ this._subtreeResolve?.(this.val);
7557
7646
  }
7558
7647
  }
7559
7648
  }
@@ -7592,6 +7681,9 @@ class Dispatcher {
7592
7681
  requestAtPath(path, name, args, opts) {
7593
7682
  return this.transactor.pushRequest(path, name, args, opts, this.parent);
7594
7683
  }
7684
+ inputAtPath(path, name, args, opts) {
7685
+ return this.transactor.pushInput(path, name, args, opts, this.parent);
7686
+ }
7595
7687
  lookupTypeFor(name, inst) {
7596
7688
  return this.transactor.comps.getCompFor(inst).scope.lookupComponent(name);
7597
7689
  }
@@ -7959,6 +8051,45 @@ function collectAppClassesInSet(app) {
7959
8051
  }
7960
8052
  return classes;
7961
8053
  }
8054
+ // src/on.js
8055
+ var OP_KINDS = ["send", "bubble", "request", "input"];
8056
+ function phaseOps(phase) {
8057
+ const ops = [];
8058
+ for (const type of OP_KINDS)
8059
+ for (const a of phase[type] ?? [])
8060
+ ops.push({ type, ...a });
8061
+ for (const a of phase.do ?? [])
8062
+ ops.push(a);
8063
+ return ops;
8064
+ }
8065
+ function resolveArgs(args, self) {
8066
+ return typeof args === "function" ? args(self) ?? [] : args ?? [];
8067
+ }
8068
+ function dispatchPhase(dispatcher, targetPath, phase, self) {
8069
+ if (!phase)
8070
+ return;
8071
+ for (const op of phaseOps(phase)) {
8072
+ const args = resolveArgs(op.args, self);
8073
+ switch (op.type) {
8074
+ case "send":
8075
+ dispatcher.sendAtPath(targetPath, op.name, args, op.opts);
8076
+ break;
8077
+ case "bubble":
8078
+ dispatcher.sendAtPath(targetPath, op.name, args, {
8079
+ skipSelf: true,
8080
+ bubbles: true,
8081
+ ...op.opts
8082
+ });
8083
+ break;
8084
+ case "request":
8085
+ dispatcher.requestAtPath(targetPath, op.name, args, op.opts);
8086
+ break;
8087
+ case "input":
8088
+ dispatcher.inputAtPath(targetPath, op.name, args, op.opts);
8089
+ break;
8090
+ }
8091
+ }
8092
+ }
7962
8093
  // src/oo.js
7963
8094
  var BAD_VALUE = Symbol("BadValue");
7964
8095
  var nullCoercer = (v) => v;
@@ -8385,8 +8516,10 @@ export {
8385
8516
  test,
8386
8517
  setIn$1 as setIn,
8387
8518
  set,
8519
+ resolveArgs,
8388
8520
  removeIn,
8389
8521
  remove,
8522
+ phaseOps,
8390
8523
  mergeWith$1 as mergeWith,
8391
8524
  mergeDeepWith$1 as mergeDeepWith,
8392
8525
  mergeDeep$1 as mergeDeep,
@@ -8419,6 +8552,7 @@ export {
8419
8552
  getIn$1 as getIn,
8420
8553
  get,
8421
8554
  fromJS,
8555
+ dispatchPhase,
8422
8556
  css,
8423
8557
  component,
8424
8558
  compileClassesToStyleText,