diff --git a/test/variable/dispose-test.js b/test/variable/dispose-test.js new file mode 100644 index 0000000..d2addd3 --- /dev/null +++ b/test/variable/dispose-test.js @@ -0,0 +1,98 @@ +import {Runtime} from "@observablehq/runtime"; +import assert from "assert"; +import {delay, sleep} from "./valueof.js"; + +describe("variable.dispose", () => { + it("prevents a subsequent delete from notifying the observer", async () => { + // https://github.com/observablehq/notebook-kit/issues/174 + const runtime = new Runtime(); + const main = runtime.module(); + const log = []; + const foo = main + .variable({fulfilled: (value) => log.push(`a-${value}`)}) + .define([], () => 1); + await sleep(); + foo.dispose(); + foo.delete(); + main + .variable({fulfilled: (value) => log.push(`b-${value}`)}) + .define([], () => 2); + await sleep(); + assert.deepStrictEqual(log, ["a-1", "b-2"]); // not followed by "a-undefined" + }); + it("prevents future computation", async () => { + const runtime = new Runtime(); + const main = runtime.module(); + const log = []; + const foo = main + .variable({fulfilled: (value) => log.push(value)}) + .define([], () => 1); + await sleep(); + foo.dispose(); + foo.define([], () => 2); + await sleep(); + assert.deepStrictEqual(log, [1]); + }); + it("cancels an in-flight computation", async () => { + const runtime = new Runtime(); + const main = runtime.module(); + const log = []; + const foo = main + .variable({fulfilled: (value) => log.push(value)}) + .define([], () => delay(1, 100)); + await sleep(); + foo.dispose(); + await sleep(200); + assert.deepStrictEqual(log, []); + }); + it("invalidates the variable", async () => { + const runtime = new Runtime(); + const main = runtime.module(); + const log = []; + const foo = main + .variable(true) + .define(["invalidation"], async (invalidation) => { + await invalidation; + log.push("invalidation"); + }); + await sleep(); + foo.dispose(); + await sleep(); + assert.deepStrictEqual(log, ["invalidation"]); + }); + it("terminates generators", async () => { + const runtime = new Runtime(); + const main = runtime.module(); + const log = []; + const foo = main.variable(true).define([], function* () { + try { + while (true) yield; + } finally { + log.push("return"); + } + }); + await sleep(); + foo.dispose(); + await sleep(); + assert.deepStrictEqual(log, ["return"]); + }); + it("terminates async generators", async () => { + const runtime = new Runtime(); + const main = runtime.module(); + const log = []; + const foo = main.variable(true).define([], async function* () { + try { + while (true) { + await sleep(); + yield; + } + } finally { + log.push("return"); + } + }); + await sleep(); + foo.dispose(); + await sleep(); + assert.deepStrictEqual(log, [ "return"]); + }); +});