Releases: localvoid/ivi
@ivi/htm 3.0.2
3.0.2
v3.0.0
v2.0.0
v2.0.0-alpha.0
- Removed all experimental features.
- Significantly reduced API, so it can be easily stabilized.
- New data structures and algorithms for UI values.
v1.0.1
v1.0.0
Components
Added second prop to components.
const Button = statelessComponent<{ id: string }, Op>((props, children) => (
button("button", props, children)
));
Button({ id: "button-id" },
"Click Me",
);
Custom areEqual
function
const View = statelessComponent<number, [number, number]>(
(a, b) => (
a + b[0] + b[1]
),
undefined,
shallowEqualArray,
);
View(1, [2, 3]);
Dirty Checking / Observables
Dirty checking API were redesigned to improve support for use cases with coarse-grained observable graphs and
mutable data structures.
New API for dirty checking is composable and can be used in stateless components.
useSelect()
hook were removed.- Added pull-based observables.
- Context is reimplemented with observables and it is now way much cheaper to dirty check.
Examples
Computed Values (lazy evaluation)
const a = observable(1);
const b = observable(2);
const sum = computed(() => watch(a) + watch(b));
const A = statelessComponent(() => div(_, _, watch(sum)()));
Basic selectors with immutable state
const STATE = { value: 1 };
const A = component((c) => {
const getValue = selector(() => STATE.value);
return () => div(_, _, watch(getValue)());
});
Memoized selector with immutable state
const STATE = { a: 1, b: 2 };
const A = component((c) => {
const getValue = selector((prev) => (
prev !== void 0 && prev.a === STATE.a && prev.b === STATE.b ? prev :
{ a: STATE.a, b: STATE.b, result: STATE.a + STATE.b };
));
return () => div(_, _, watch(getValue)());
});
Composition
const a = observable(1);
const A = component((c) => {
const getValue = memo((i) => computed(() => watch(a) + i));
return (i) => div(_, _, watch(getValue(i))());
});
Boolean DOM Attribute Values
Removed automagic conversion from boolean values to empty string. Correct attribute values should be specified
explicitly.
textContent=""
Optimization
This optimization has a quite noticeable impact in popular benchmarks. But in real applications, use cases that would benefit from this optimization will work significantly faster by wrapping lists into a transient DOM node.
Deep State Tracking
Deep state tracking optimization were removed. It is one of those optimizations that improve performance in benchmarks, but make it worse in real applications.
This optimization worked by updating node state flags during stack unwinding. It saved information about node subtree, so we could skip dirty checking and unmounting for subtrees that didn't have any stateful components. In applications decomposed into small components there will be many stateful components used as leaf nodes, so instead of optimizing, it will make dirty checking and reconciliation algorithms slightly slower. Also, this optimization were adding a lot of complexity to the reconciliation algorithm.
Simplified track by key algorithm
Instead of returning LIS indices, nodes that are part of LIS are now marked in the input array.
Events
Stop Propagation
Synthetic event handlers do not propagate events anymore. To propagate events, event handler should return
DispatchEvent.Propagate
value.
Move Events
Removed touch/mouse/pointer move events. Move event handlers usually attached when down event is triggered. To make sure that we don't lose any move events, we can't wait until next frame is rerendered, so move event handlers should be attached with native DOM api.
Server Side Rendering
Removed. Not interested in supporting this feature.
v0.27.1
v0.27.0
Optimizations
Reduced memory consumption by operation nodes. All properties are now inlined into operation nodes and there are three different operation node shapes. Almost all callsites should stay in monomorphic state, except for the one that accessing operation type in the mount and update functions, it will be in polymorphic state and it is ok as long as it doesn't transition into megamorphic state.
Bug Fixes
- Fixed
nextNode
assignment in a dirty checking algorithm when it is going through DOM elements.
v0.26.0
Optimizations
Reduced memory consumption in component hooks, refs and portals.
API that is used for this optimizations is now public. This API is using several objects: TASK_TOKEN
, SELECT_TOKEN
and UNMOUNT_TOKEN
to identify who is invoking a callback function. Callbacks registered with scheduleMicrotask()
will receive TASK_TOKEN
as a first argument, hooks added with useUnmount()
will receive UNMOUNT_TOKEN
. SELECT_TOKEN
is used internally to optimize useSelect()
.
Immediately executed useEffect()
useEffect()
hook is now immediately executed when it is invoked in the internal component "update" function. It makes it fully deterministic to prevent unexpected bugs when useEffect()
is used to listen some observable value that can generate an event before microtask with an effect is executed. When it is immediately executed, it will guarantee that we don't miss any events generated by an observable value.