Compare commits

...

9 Commits

Author SHA1 Message Date
funman300 331d932c4b Merge pull request 'docs(core): record unlimited stock recycling as an intentional rules decision' (#122) from docs/recycle-rule-decision into master
Web WASM Rebuild / rebuild (push) Has been cancelled
Build and Deploy / build-and-push (push) Successful in 6m32s
Web E2E / web-e2e (push) Successful in 5m1s
2026-07-06 20:10:00 +00:00
Gitea CI 716e5f04cf chore(web): regenerate wasm artifacts
Build and Deploy / build-and-push (push) Successful in 6m40s
Web E2E / web-e2e (push) Successful in 6m17s
2026-07-06 20:03:54 +00:00
funman300 ef9d914b99 docs(core): record unlimited stock recycling as an intentional rules decision
Resolves the Draw-1 recycle question from the June 500-game audit:
unlimited recycling with upstream score penalties is deliberate,
matching mainstream digital solitaire rather than strict 3-pass
tournament rules. The difficulty seed catalog and the winnable-deal
solver are verified under this rule, so a hard pass limit must not be
introduced casually.

- ARCHITECTURE.md: new 'Rules decisions' note in the solitaire_core
  section
- GameState::draw() doc comment points at the decision record
- New lock-in test draw_one_recycling_is_unlimited_by_design asserts
  10+ recycles are never rejected

Closes #117

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:03:22 -07:00
funman300 005efa2ee4 Merge pull request 'fix(engine): re-poll safe-area insets after app resume' (#121) from fix/safe-area-resume-repoll into master
Build and Deploy / build-and-push (push) Successful in 3m18s
Web WASM Rebuild / rebuild (push) Successful in 8m43s
2026-07-06 19:52:59 +00:00
funman300 1190ed3ce6 fix(engine): re-poll safe-area insets after app resume
refresh_insets gated its loop on insets.is_populated(), so once insets
resolved at first launch, rearm_on_resumed's poll-counter reset was a
no-op and JNI was never queried again. Insets that changed while the
app was backgrounded (fold/unfold, rotation, gesture/3-button nav
switch) stayed stale until process restart.

Gate the loop on the poll counter alone and settle a cycle by
exhausting it once a populated reading arrives. The cached resource is
rewritten only when the value actually differs, so resumes where
nothing moved trigger no change detection and no relayout — preserving
the no-flash resume behaviour. Also correct the stale on_app_resumed
doc that still described the old inset-zeroing approach.

Closes #116

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:50:01 -07:00
Gitea CI 2869e1c34e chore(web): regenerate wasm artifacts
Build and Deploy / build-and-push (push) Successful in 5m50s
Web E2E / web-e2e (push) Successful in 4m55s
2026-06-26 21:25:24 +00:00
funman300 783f01628e Merge pull request 'fix(engine): raise dynamic tableau fan cap to fill tall viewports' (#115) from fix/cover-screen-fan-cap into master
Build and Deploy / build-and-push (push) Successful in 2m8s
Web WASM Rebuild / rebuild (push) Successful in 7m24s
Android Release / build-apk (push) Successful in 5m17s
2026-06-26 21:15:53 +00:00
funman300 94a6feb5db fix(engine): raise dynamic tableau fan cap to fill tall viewports
MAX_DYNAMIC_FAN_FRAC 0.6 -> 0.9 so the dynamic tableau fill spreads
further on very tall / narrow viewports (e.g. a foldable cover screen),
which were left ~40% empty at the cap. Fills the unfolded near-square
screen to ~100% and lets the cover screen fill further (and the rest fills
as columns deepen during play). Normal phones are unaffected — their fill
fraction is already below the cap. apply_dynamic_tableau_fan still floors
at TABLEAU_FAN_FRAC and deeper columns drive the fraction down, so nothing
overflows and hit-testing stays in sync.

Vertical centring of the residual was investigated but dropped: a 21:9
phone is aspect-identical to the cover screen, so centring can't be
targeted to foldables without also disconnecting the board from the HUD on
tall phones.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 13:56:31 -07:00
Gitea CI 3daaf47689 chore(web): regenerate wasm artifacts
Build and Deploy / build-and-push (push) Successful in 6m3s
Web E2E / web-e2e (push) Successful in 4m47s
2026-06-26 20:20:59 +00:00
8 changed files with 136 additions and 75 deletions
+12
View File
@@ -109,6 +109,18 @@ Owns:
- Achievement unlock condition evaluation - Achievement unlock condition evaluation
- Seeded RNG for reproducible deals - Seeded RNG for reproducible deals
**Rules decisions:**
- **Stock recycling is unlimited in every draw mode — by design.** Extra
passes through the stock are discouraged via the upstream score penalty
(applied by the `card_game`/`klondike` session), never blocked with a
`MoveError`. This matches mainstream digital solitaire (unlimited redeals
in Draw-1) rather than strict tournament rules (3-pass cap). It is load-
bearing: the difficulty seed catalog and the winnable-deal solver are
verified under unlimited recycling, so introducing a hard pass limit would
invalidate both. Locked in by the
`draw_one_recycling_is_unlimited_by_design` test in
`solitaire_core/src/game_state.rs`. (Decision record: Gitea issue #117.)
### `solitaire_sync` ### `solitaire_sync`
**Dependencies:** `serde`, `serde_json`, `uuid`, `chrono` only. **Dependencies:** `serde`, `serde_json`, `uuid`, `chrono` only.
+9 -1
View File
@@ -8,6 +8,12 @@ project follows [Semantic Versioning](https://semver.org/).
### Added ### Added
- **Rules decision record: unlimited stock recycling.** Documented in
`ARCHITECTURE.md` that unlimited recycling with score penalties (matching
mainstream digital solitaire) is intentional, and locked it in with a core
test — the difficulty seed catalog and winnable-deal solver are verified
under this rule. Resolves the last open finding from the June 500-game
audit (issue #117).
- **Analytics validation runbook.** Documented native Matomo live validation, - **Analytics validation runbook.** Documented native Matomo live validation,
expected event payloads, and the current web/WASM analytics split. expected event payloads, and the current web/WASM analytics split.
- **Android smoke-test runbook.** Updated the Android doc with the current - **Android smoke-test runbook.** Updated the Android doc with the current
@@ -41,7 +47,9 @@ project follows [Semantic Versioning](https://semver.org/).
each column's total depth (face-down cards included) and refills on the each column's total depth (face-down cards included) and refills on the
cold-start deal, every move, and on resize (incl. the Android safe-area-inset cold-start deal, every move, and on resize (incl. the Android safe-area-inset
resize and fold/unfold), so a near-square viewport such as an unfolded Galaxy resize and fold/unfold), so a near-square viewport such as an unfolded Galaxy
Fold no longer leaves the bottom of the screen empty. Fold no longer leaves the bottom of the screen empty. The fan spread cap was
raised so very tall / narrow viewports (e.g. a foldable cover screen) fill
further.
- **Card-move animation jank.** A move now rebuilds a card's child visuals only - **Card-move animation jank.** A move now rebuilds a card's child visuals only
when its appearance changes (flip / resize / accessibility) instead of when its appearance changes (flip / resize / accessibility) instead of
despawning and respawning every card's children each `StateChangedEvent`, despawning and respawning every card's children each `StateChangedEvent`,
+31
View File
@@ -863,6 +863,13 @@ impl GameState {
} }
/// Draw cards from stock to waste. When stock is empty, recycles waste back to stock. /// Draw cards from stock to waste. When stock is empty, recycles waste back to stock.
///
/// Recycling is deliberately unlimited in every draw mode: extra passes
/// are discouraged through the upstream score penalty, never rejected
/// with a [`MoveError`]. The difficulty seed catalog and the
/// winnable-deal solver are verified under this rule — see the
/// "Rules decisions" note in `ARCHITECTURE.md` (`solitaire_core`
/// section) before considering a hard pass limit.
pub fn draw(&mut self) -> Result<(), MoveError> { pub fn draw(&mut self) -> Result<(), MoveError> {
if self.is_won() { if self.is_won() {
return Err(MoveError::GameAlreadyWon); return Err(MoveError::GameAlreadyWon);
@@ -1222,6 +1229,30 @@ mod tests {
); );
} }
#[test]
fn draw_one_recycling_is_unlimited_by_design() {
// Rules decision (Gitea #117): stock recycling is unlimited in every
// draw mode. Extra passes are discouraged via the upstream score
// penalty, never blocked with a MoveError. The difficulty seed
// catalog and the winnable-deal solver are verified under this rule,
// so a hard pass limit must not be introduced casually — see the
// "Rules decisions" note in ARCHITECTURE.md (`solitaire_core`).
let mut game = game_at_first_recycle().expect("could not reach recycle");
// ~24 draws per Draw-1 pass; 2_000 draws is ample budget for 10 passes.
for _ in 0..2_000 {
if game.recycle_count() >= 10 {
break;
}
game.draw()
.expect("unlimited recycling: draw must never fail on pass count");
}
assert!(
game.recycle_count() >= 10,
"expected at least 10 recycles within the draw budget, got {}",
game.recycle_count(),
);
}
#[test] #[test]
fn undo_applies_minus_15_penalty_via_upstream_score() { fn undo_applies_minus_15_penalty_via_upstream_score() {
// A foundation move scores +10 upstream; undoing it nets the move score // A foundation move scores +10 upstream; undoing it nets the move score
+9 -13
View File
@@ -99,7 +99,7 @@ const MAX_TABLEAU_CARDS: f32 = 13.0;
/// clear overlap (a readable stack) while still filling most of a near-square / /// clear overlap (a readable stack) while still filling most of a near-square /
/// unfolded-foldable screen. Tunable purely for feel — no effect on correctness /// unfolded-foldable screen. Tunable purely for feel — no effect on correctness
/// or hit-testing. /// or hit-testing.
pub(crate) const MAX_DYNAMIC_FAN_FRAC: f32 = 0.6; pub(crate) const MAX_DYNAMIC_FAN_FRAC: f32 = 0.9;
/// Vertical pixel band reserved at the top of the play area for the HUD /// Vertical pixel band reserved at the top of the play area for the HUD
/// (action buttons, Score / Moves / Timer readouts). The card grid starts /// (action buttons, Score / Moves / Timer readouts). The card grid starts
@@ -285,13 +285,12 @@ pub fn compute_layout(
); );
} }
// Adaptive tableau fan fraction. On height-limited (desktop) windows the // Adaptive tableau fan fraction. On height-limited windows the height-based
// height-based sizing already ensures a worst-case 13-card column fits at // sizing already ensures a worst-case 13-card column fits at TABLEAU_FAN_FRAC,
// TABLEAU_FAN_FRAC (0.25), so the formula returns ≈0.25 and the clamp // so the formula returns the minimum and the clamp keeps it there. On
// keeps it there — no change from prior behaviour. On width-limited // width-limited (portrait phone) windows card_size is small and lots of
// (portrait phone) windows card_size is small and lots of vertical space // vertical space is unused; solve for the fraction that fills the available
// is unused; we solve for the fraction that exactly fills the available // space. `apply_dynamic_tableau_fan` later refines this for the actual deal.
// space to the bottom margin.
// //
// avail = distance from the top of the first tableau card to the bottom // avail = distance from the top of the first tableau card to the bottom
// margin — i.e. the space available for 12 fan steps. // margin — i.e. the space available for 12 fan steps.
@@ -302,20 +301,17 @@ pub fn compute_layout(
} else { } else {
TABLEAU_FAN_FRAC TABLEAU_FAN_FRAC
}; };
// Never go below the desktop minimum — avoids shrinking the fan on
// degenerate near-square windows where the formula might undershoot.
let tableau_fan_frac = ideal_fan_frac.max(TABLEAU_FAN_FRAC); let tableau_fan_frac = ideal_fan_frac.max(TABLEAU_FAN_FRAC);
// Scale the face-down fraction proportionally so rendering and hit-testing
// stay in sync (TABLEAU_FACEDOWN_FAN_FRAC / TABLEAU_FAN_FRAC = 0.48 ratio).
let facedown_scale = TABLEAU_FACEDOWN_FAN_FRAC / TABLEAU_FAN_FRAC; let facedown_scale = TABLEAU_FACEDOWN_FAN_FRAC / TABLEAU_FAN_FRAC;
let tableau_facedown_fan_frac = tableau_fan_frac * facedown_scale; let tableau_facedown_fan_frac = tableau_fan_frac * facedown_scale;
let available_tableau_height = avail;
Layout { Layout {
card_size, card_size,
pile_positions, pile_positions,
tableau_fan_frac, tableau_fan_frac,
tableau_facedown_fan_frac, tableau_facedown_fan_frac,
available_tableau_height: avail, available_tableau_height,
} }
} }
+27 -13
View File
@@ -191,10 +191,12 @@ fn apply_safe_area_to_modal_scrims(
/// whatever `SafeAreaInsets` are current at that moment. /// whatever `SafeAreaInsets` are current at that moment.
/// ///
/// On Android the `android::rearm_on_resumed` system runs in the same frame /// On Android the `android::rearm_on_resumed` system runs in the same frame
/// and resets both `SafeAreaPollTries` and `SafeAreaInsets` to zero, causing /// and resets `SafeAreaPollTries` (the cached `SafeAreaInsets` keep their
/// `refresh_insets` to re-poll JNI over the next few frames. When it resolves /// last-known values), causing `refresh_insets` to re-poll JNI over the next
/// the correct values, `on_safe_area_changed` in `table_plugin` emits a second /// few frames. If the insets changed while backgrounded, `on_safe_area_changed`
/// synthetic `WindowResized` and the layout converges to the right position. /// in `table_plugin` emits a second synthetic `WindowResized` and the layout
/// converges to the right position; if they didn't, nothing is rewritten and
/// the layout stays put.
/// ///
/// On non-Android targets this handler still fires — it ensures that a resume /// On non-Android targets this handler still fires — it ensures that a resume
/// event always refreshes the layout (e.g., after a minimise/restore on /// event always refreshes the layout (e.g., after a minimise/restore on
@@ -232,9 +234,14 @@ mod android {
pub(super) struct SafeAreaPollTries(pub u32); pub(super) struct SafeAreaPollTries(pub u32);
/// Polls Android for safe-area insets until we get a non-zero /// Polls Android for safe-area insets until we get a non-zero
/// reading, then stops. `getRootWindowInsets()` returns `null` (or /// reading, then settles until [`rearm_on_resumed`] re-arms it on the
/// all-zero `Insets`) until the decor view has been laid out, which /// next foreground resume — insets can change while backgrounded
/// is typically frame 13 of a fresh launch. /// (rotation, fold/unfold, gesture ↔ 3-button nav). The poll counter
/// (not `insets.is_populated()`) gates the loop, so a re-armed cycle
/// re-queries JNI even though cached values are already populated.
/// `getRootWindowInsets()` returns `null` (or all-zero `Insets`)
/// until the decor view has been laid out, which is typically frame
/// 13 of a fresh launch.
pub(super) fn refresh_insets( pub(super) fn refresh_insets(
mut insets: ResMut<SafeAreaInsets>, mut insets: ResMut<SafeAreaInsets>,
mut poll: ResMut<SafeAreaPollTries>, mut poll: ResMut<SafeAreaPollTries>,
@@ -243,18 +250,25 @@ mod android {
// devices that genuinely report zero insets. // devices that genuinely report zero insets.
const MAX_TRIES: u32 = 120; // ~2 seconds @ 60 fps const MAX_TRIES: u32 = 120; // ~2 seconds @ 60 fps
if poll.0 >= MAX_TRIES || insets.is_populated() { if poll.0 >= MAX_TRIES {
return; return;
} }
poll.0 += 1; poll.0 += 1;
match query_insets() { match query_insets() {
Ok(v) if v.is_populated() => { Ok(v) if v.is_populated() => {
info!( if *insets != v {
"safe_area: insets resolved top={} bottom={} left={} right={} (after {} frames)", info!(
v.top, v.bottom, v.left, v.right, poll.0 "safe_area: insets resolved top={} bottom={} left={} right={} (after {} frames)",
); v.top, v.bottom, v.left, v.right, poll.0
*insets = v; );
*insets = v;
}
// Settled for this poll cycle; `rearm_on_resumed` re-arms on
// the next resume. Writing `insets` only on an actual change
// keeps resource change detection (and the relayout it
// triggers) quiet on resumes where nothing moved.
poll.0 = MAX_TRIES;
} }
Ok(_) => { Ok(_) => {
// Layout not ready yet; try again next frame. // Layout not ready yet; try again next frame.
+48 -48
View File
@@ -1649,63 +1649,63 @@ function __wbg_get_imports() {
return ret; return ret;
}, },
__wbindgen_cast_0000000000000001: function(arg0, arg1) { __wbindgen_cast_0000000000000001: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 114855, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 114857, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hea4b5125da4e5ded); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hfb2e9a2f0bbd9ecc);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000002: function(arg0, arg1) { __wbindgen_cast_0000000000000002: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000003: function(arg0, arg1) { __wbindgen_cast_0000000000000003: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>"), NamedExternref("ResizeObserver")], shim_idx: 9847, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>"), NamedExternref("ResizeObserver")], shim_idx: 9843, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h0fec466277fb30e8); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h876550298b312ff8);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000004: function(arg0, arg1) { __wbindgen_cast_0000000000000004: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_3); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_3);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000005: function(arg0, arg1) { __wbindgen_cast_0000000000000005: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_4); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_4);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000006: function(arg0, arg1) { __wbindgen_cast_0000000000000006: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("FocusEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("FocusEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_5); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_5);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000007: function(arg0, arg1) { __wbindgen_cast_0000000000000007: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_6); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_6);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000008: function(arg0, arg1) { __wbindgen_cast_0000000000000008: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PageTransitionEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PageTransitionEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_7); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_7);
return ret; return ret;
}, },
__wbindgen_cast_0000000000000009: function(arg0, arg1) { __wbindgen_cast_0000000000000009: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_8); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_8);
return ret; return ret;
}, },
__wbindgen_cast_000000000000000a: function(arg0, arg1) { __wbindgen_cast_000000000000000a: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("WheelEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("WheelEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_9); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_9);
return ret; return ret;
}, },
__wbindgen_cast_000000000000000b: function(arg0, arg1) { __wbindgen_cast_000000000000000b: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Option(NamedExternref("Blob"))], shim_idx: 9843, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Option(NamedExternref("Blob"))], shim_idx: 9840, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hf05069bc44820cc5); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h657f46feffff6fe4);
return ret; return ret;
}, },
__wbindgen_cast_000000000000000c: function(arg0, arg1) { __wbindgen_cast_000000000000000c: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 9839, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 9834, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h5e26b448f43bfba9); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h545edb23183e448a);
return ret; return ret;
}, },
__wbindgen_cast_000000000000000d: function(arg0) { __wbindgen_cast_000000000000000d: function(arg0) {
@@ -1769,55 +1769,55 @@ function __wbg_get_imports() {
}; };
} }
function wasm_bindgen__convert__closures_____invoke__h5e26b448f43bfba9(arg0, arg1) { function wasm_bindgen__convert__closures_____invoke__h545edb23183e448a(arg0, arg1) {
wasm.wasm_bindgen__convert__closures_____invoke__h5e26b448f43bfba9(arg0, arg1); wasm.wasm_bindgen__convert__closures_____invoke__h545edb23183e448a(arg0, arg1);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_3(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_3(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_3(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_3(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_4(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_4(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_4(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_4(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_5(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_5(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_5(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_5(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_6(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_6(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_6(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_6(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_7(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_7(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_7(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_7(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_8(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_8(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_8(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_8(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_9(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_9(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_9(arg0, arg1, arg2); wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_9(arg0, arg1, arg2);
} }
function wasm_bindgen__convert__closures_____invoke__hea4b5125da4e5ded(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__hfb2e9a2f0bbd9ecc(arg0, arg1, arg2) {
const ret = wasm.wasm_bindgen__convert__closures_____invoke__hea4b5125da4e5ded(arg0, arg1, arg2); const ret = wasm.wasm_bindgen__convert__closures_____invoke__hfb2e9a2f0bbd9ecc(arg0, arg1, arg2);
if (ret[1]) { if (ret[1]) {
throw takeFromExternrefTable0(ret[0]); throw takeFromExternrefTable0(ret[0]);
} }
} }
function wasm_bindgen__convert__closures_____invoke__h0fec466277fb30e8(arg0, arg1, arg2, arg3) { function wasm_bindgen__convert__closures_____invoke__h876550298b312ff8(arg0, arg1, arg2, arg3) {
wasm.wasm_bindgen__convert__closures_____invoke__h0fec466277fb30e8(arg0, arg1, arg2, arg3); wasm.wasm_bindgen__convert__closures_____invoke__h876550298b312ff8(arg0, arg1, arg2, arg3);
} }
function wasm_bindgen__convert__closures_____invoke__hf05069bc44820cc5(arg0, arg1, arg2) { function wasm_bindgen__convert__closures_____invoke__h657f46feffff6fe4(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__hf05069bc44820cc5(arg0, arg1, isLikeNone(arg2) ? 0 : addToExternrefTable0(arg2)); wasm.wasm_bindgen__convert__closures_____invoke__h657f46feffff6fe4(arg0, arg1, isLikeNone(arg2) ? 0 : addToExternrefTable0(arg2));
} }
Binary file not shown.
Binary file not shown.