From 4b1a94d9900d0b40d8bc7ba769d5af1e7ed864fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 24 Jun 2022 22:55:55 +0200 Subject: [PATCH] wip --- src/runtime/component_node.ts | 8 ++--- src/runtime/utils.ts | 27 ---------------- tests/reactivity.test.ts | 59 ----------------------------------- tests/utils.test.ts | 39 +---------------------- 4 files changed, 5 insertions(+), 128 deletions(-) diff --git a/src/runtime/component_node.ts b/src/runtime/component_node.ts index 0a9cd135..897a6109 100644 --- a/src/runtime/component_node.ts +++ b/src/runtime/component_node.ts @@ -41,7 +41,7 @@ function applyDefaultProps

(props: P, defaultProps: Partial

) // Integration with reactivity system (useState) // ----------------------------------------------------------------------------- -const batchedRenderFunctions = new WeakMap(); +const renderFunctions = new WeakMap(); /** * Creates a reactive object that will be observed by the current component. * Reading data from the returned object (eg during rendering) will cause the @@ -54,10 +54,10 @@ const batchedRenderFunctions = new WeakMap(); */ export function useState(state: T): Reactive | NonReactive { const node = getCurrent(); - let render = batchedRenderFunctions.get(node)!; + let render = renderFunctions.get(node)!; if (!render) { render = node.render.bind(node, false); - batchedRenderFunctions.set(node, render); + renderFunctions.set(node, render); // manual implementation of onWillDestroy to break cyclic dependency node.willDestroy.push(clearReactivesForCallback.bind(null, render)); } @@ -366,7 +366,7 @@ export class ComponentNode

implements VNode { - const render = batchedRenderFunctions.get(this); + const render = renderFunctions.get(this); return render ? getSubscriptions(render) : []; } } diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts index 48166239..d0d3a387 100644 --- a/src/runtime/utils.ts +++ b/src/runtime/utils.ts @@ -1,32 +1,5 @@ export type Callback = () => void; -/** - * Creates a batched version of a callback so that all calls to it in the same - * microtick will only call the original callback once. - * - * @param callback the callback to batch - * @returns a batched version of the original callback - */ -export function batched(callback: Callback): Callback { - let called = false; - return async () => { - debugger; - // This await blocks all calls to the callback here, then releases them sequentially - // in the next microtick. This line decides the granularity of the batch. - await Promise.resolve(); - if (!called) { - called = true; - // wait for all calls in this microtick to fall through before resetting "called" - // so that only the first call to the batched function calls the original callback. - // Schedule this before calling the callback so that calls to the batched function - // within the callback will proceed only after resetting called to false, and have - // a chance to execute the callback again - Promise.resolve().then(() => (called = false)); - callback(); - } - }; -} - export function validateTarget(target: HTMLElement) { if (!(target instanceof HTMLElement)) { throw new Error("Cannot mount component: the target is not a valid DOM element"); diff --git a/tests/reactivity.test.ts b/tests/reactivity.test.ts index 751ee5a7..20ebeb42 100644 --- a/tests/reactivity.test.ts +++ b/tests/reactivity.test.ts @@ -10,7 +10,6 @@ import { toRaw, } from "../src"; import { reactive, Reactive } from "../src/runtime/reactivity"; -import { batched } from "../src/runtime/utils"; import { makeDeferred, makeTestFixture, @@ -190,64 +189,6 @@ describe("Reactivity", () => { expect(n).toBe(2); }); - test("batched: callback is called after batch of operation", async () => { - let n = 0; - const state = createReactive( - { a: 1, b: 2 }, - batched(() => n++) - ); - state.a = 2; - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(0); // key has not be read yet - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(0); - state.b = state.b + 5; // key is read and then modified - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(1); // two operations but only one notification - }); - - test("batched: modifying the reactive in the callback doesn't break reactivity", async () => { - let n = 0; - let obj = { a: 1 }; - const state = createReactive( - obj, - batched(() => { - state.a; // subscribe to a - state.a = 2; - n++; - }) - ); - expect(n).toBe(0); - state.a = 2; - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(0); // key has not be read yet - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(1); - // the write a = 2 inside the batched callback triggered another notification, wait for it - await nextMicroTick(); - expect(n).toBe(2); - // Should now be stable as we're writing the same value again - await nextMicroTick(); - expect(n).toBe(2); - - // Do it again to check it's not broken - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(2); - await nextMicroTick(); - expect(n).toBe(3); - // the write a = 2 inside the batched callback triggered another notification, wait for it - await nextMicroTick(); - expect(n).toBe(4); - // Should now be stable as we're writing the same value again - await nextMicroTick(); - expect(n).toBe(4); - }); - test("setting property to same value does not trigger callback", async () => { let n = 0; const state = createReactive({ a: 1 }, () => n++); diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 29a109fa..d2db69a2 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -1,4 +1,4 @@ -import { batched, EventBus } from "../src/runtime/utils"; +import { EventBus } from "../src/runtime/utils"; import { nextMicroTick } from "./helpers"; describe("event bus behaviour", () => { @@ -34,40 +34,3 @@ describe("event bus behaviour", () => { bus.trigger("event", "hello world"); }); }); - -describe("batched", () => { - test("callback is called only once after operations", async () => { - let n = 0; - let fn = batched(() => n++); - - expect(n).toBe(0); - fn(); - fn(); - expect(n).toBe(0); - - await nextMicroTick(); - expect(n).toBe(1); - await nextMicroTick(); - expect(n).toBe(1); - }); - - test("calling batched function from within the callback is not treated as part of the original batch", async () => { - let n = 0; - let fn = batched(() => { - n++; - if (n === 1) { - fn(); - } - }); - - expect(n).toBe(0); - fn(); - expect(n).toBe(0); - await nextMicroTick(); // First batch - expect(n).toBe(1); - await nextMicroTick(); // Second batch initiated from within the callback - expect(n).toBe(2); - await nextMicroTick(); - expect(n).toBe(2); - }); -});