Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
gordonbrander / actor.ts
Last active February 25, 2025 13:48
Simple actors with async and TransformStream
import { type Receive, type Send, useMailbox } from "./mailbox.ts";
export type Context<Msg> = {
self: string;
send: (id: string, msg: Msg) => Promise<void>;
receive: Receive<Msg>;
spawn: (id: string, actor: Actor<Msg>) => string;
};
export type Actor<Msg> = (context: Context<Msg>) => Promise<void>;
@gordonbrander
gordonbrander / pipe.rs
Created November 24, 2024 15:42
pipe.rs - rust pipeline macro
#[macro_export]
macro_rules! pipe {
// Base case - single function
($value:expr, $func:expr) => {
$func($value)
};
// Recursive case - multiple functions
($value:expr, $func:expr, $($rest:expr),+) => {
pipe!($func($value), $($rest),+)
@gordonbrander
gordonbrander / middleware.test.ts
Last active November 6, 2024 02:14
middleware.ts - functional-style middleware
import { strict as assert } from "assert";
import { createMiddleware, Msg } from "./middleware.js";
describe("createMiddleware", () => {
it("should create middleware with empty initial state", () => {
const middleware = createMiddleware();
assert.deepEqual(middleware("test"), "test");
});
it("should execute single middleware", () => {
@gordonbrander
gordonbrander / transition.ts
Last active October 2, 2024 14:23
transition.ts - micro JS CSS transitions helper
let slowAnimations = false;
/** Set slow animations for debugging */
export const setSlowAnimations = (isSlow: boolean) => {
slowAnimations = isSlow;
};
/** @returns 10s if slow animations is turned on, otherwise returns `ms` */
export const slowable = (ms: number) => (slowAnimations ? 10000 : ms);
@gordonbrander
gordonbrander / multidispatch.ts
Created August 3, 2024 19:38
multidispatch.ts
export const multidispatch = <T>() => {
const routes = new Map<
(...args: unknown[]) => boolean,
(...args: unknown[]) => T
>();
const call = (...args: unknown[]) => {
for (const [isMatch, handler] of routes.entries()) {
if (isMatch(...args)) {
return handler(...args);
@gordonbrander
gordonbrander / h.js
Last active October 5, 2023 23:04
h.js - hyperscript micro implementation
// Set key on object, but only if value has changed.
// This is useful when setting keys on DOM elements, where setting the same
// value may trigger a style recalc.
//
// Note that the typical layout-triggering DOM properties are read-only,
// so this is safe to use to write to DOM element properties.
// See https://gist.github.com/paulirish/5d52fb081b3570c81e3a.
export const prop = (object, key, value) => {
if (object[key] !== value) {
object[key] = value
@gordonbrander
gordonbrander / prop.js
Created September 28, 2023 02:15
prop.js - make DOM fast with a write-through cache
// Set property of element.
// Uses a write-through cache to only set
// when value actually changes.
export const prop = (el, key, value) => {
let cacheKey = Symbol.from(`prop.${key}`)
if (el[cacheKey] != value) {
el[cacheKey] = value
el[key] = value
}
}
@gordonbrander
gordonbrander / async-mailbox.js
Created May 14, 2023 00:46
async-mailbox.js - async generator publisher
export const sleep = ms => new Promise(resolve => {
setTimeout(resolve, ms)
})
export const hz = x => (1/x * 1000)
const complete = Symbol('complete')
export class Mailbox {
#buffer = []
@gordonbrander
gordonbrander / cdom.js
Created March 26, 2023 01:41
cdom.js - cached dom writers that only write if property value changed
// CDOM - Cached DOM
// CDOM minimizes DOM writes by caching last written value and only touching the
// DOM when a new value does not equal the cached value.
// The goal of CDOM is to make it safe to "bash the DOM" as often as you like
// without affecting performance, even bashing it every frame.
// Create a cached setter
export const CachedSetter = (ns, set) => (el, value) => {
let cacheKey = Symbol.for(`CachedSetter::${ns}`)
if (el[cacheKey] !== value) {
@gordonbrander
gordonbrander / modest-example.js
Last active March 25, 2023 19:39
Modest - a modest framework for unambitious web apps. One file. No dependencies. No build steps.
import {StoreElement, change} from './modest.js'
class ModestApp extends StoreElement {
static template() {
return `
<style>
:host {
display: block;
}
.time {