Skip to content

Commit

Permalink
✨ Add a new 'ForceModel' debug action to experiment with time-travel …
Browse files Browse the repository at this point in the history
…debugging.
  • Loading branch information
hayleigh-dot-dev committed Apr 16, 2024
1 parent 5d5b513 commit 7a145f6
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
32 changes: 31 additions & 1 deletion src/client-runtime.ffi.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ElementNotFound, NotABrowser } from "./lustre.mjs";
import { Dispatch, Shutdown } from "./lustre/internals/runtime.mjs";
import {
Dispatch,
Shutdown,
Debug,
ForceModel,
} from "./lustre/internals/runtime.mjs";
import { morph } from "./vdom.ffi.mjs";
import { Ok, Error, isEqual } from "./gleam.mjs";

Expand Down Expand Up @@ -58,6 +63,11 @@ export class LustreClientApplication {
return;
}

case action instanceof Debug: {
this.#debug(action[0]);
return;
}

default:
return;
}
Expand Down Expand Up @@ -114,6 +124,26 @@ export class LustreClientApplication {
}
}

#debug(action) {
switch (true) {
case action instanceof ForceModel: {
const vdom = this.#view(this.#model);
const dispatch = (handler) => (e) => {
const result = handler(e);

if (result instanceof Ok) {
this.send(new Dispatch(result[0]));
}
};

this.#queue = [];
this.#effects = [];
this.#didUpdate = false;
this.#root = morph(this.#root, vdom, dispatch, this.#isComponent);
}
}
}

#shutdown() {
this.#root.remove();
this.#root = null;
Expand Down
18 changes: 17 additions & 1 deletion src/lustre/internals/runtime.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import gleam/dict.{type Dict}
import gleam/dynamic.{type Decoder, type Dynamic}
import gleam/erlang/process.{type Selector, type Subject}
import gleam/list
import gleam/json.{type Json}
import gleam/list
import gleam/option.{Some}
import gleam/otp/actor.{type Next, type StartError, Spec}
import gleam/result
Expand Down Expand Up @@ -46,6 +46,7 @@ pub type Action(msg, runtime) {
}

pub type DebugAction {
ForceModel(Dynamic)
Model(reply: fn(Dynamic) -> Nil)
View(reply: fn(Element(Dynamic)) -> Nil)
}
Expand Down Expand Up @@ -133,6 +134,21 @@ fn loop(
loop(Batch(rest, effect.batch([effects, other_effects])), next)
}

Debug(ForceModel(model)) -> {
let model = dynamic.unsafe_coerce(model)
let html = state.view(model)
let diff = patch.elements(state.html, html)
let next =
State(..state, model: model, html: html, handlers: diff.handlers)

case patch.is_empty_element_diff(diff) {
True -> Nil
False -> run_renderers(state.renderers, Diff(diff))
}

actor.continue(next)
}

Debug(Model(reply)) -> {
reply(dynamic.from(state.model))
actor.continue(state)
Expand Down

0 comments on commit 7a145f6

Please sign in to comment.