File tree Expand file tree Collapse file tree 5 files changed +89
-0
lines changed Expand file tree Collapse file tree 5 files changed +89
-0
lines changed Original file line number Diff line number Diff line change @@ -6,11 +6,13 @@ import {group} from "d3-array";
66import { dispatch as d3Dispatch } from "d3-dispatch" ;
77import * as stdlib from "./stdlib.js" ;
88import { OUTPUT_MARK } from "./constant.js" ;
9+ import { Mutable } from "./mutable.js" ;
910
1011const PREFIX = `//${ OUTPUT_MARK } ` ;
1112
1213const BUILTINS = {
1314 recho : ( ) => stdlib ,
15+ Mutable : ( ) => Mutable ,
1416} ;
1517
1618function uid ( ) {
Original file line number Diff line number Diff line change 1+ // https://github.com/observablehq/notebook-kit/blob/main/src/runtime/stdlib/mutable.ts
2+ import { observe } from "./observe.js" ;
3+
4+ // Mutable returns a generator with a value getter/setting that allows the
5+ // generated value to be mutated. Therefore, direct mutation is only allowed
6+ // within the defining cell, but the cell can also export functions that allows
7+ // other cells to mutate the value as desired.
8+ export function Mutable ( value ) {
9+ let change = undefined ;
10+ const mutable = observe ( ( _ ) => {
11+ change = _ ;
12+ if ( value !== undefined ) change ( value ) ;
13+ } ) ;
14+ return Object . defineProperty ( mutable , "value" , {
15+ get : ( ) => value ,
16+ set : ( x ) => ( ( value = x ) , void change ?. ( value ) ) ,
17+ } ) ;
18+ }
19+
20+ export function Mutator ( value ) {
21+ const mutable = Mutable ( value ) ;
22+ return [
23+ mutable ,
24+ {
25+ get value ( ) {
26+ return mutable . value ;
27+ } ,
28+ set value ( v ) {
29+ mutable . value = v ;
30+ } ,
31+ } ,
32+ ] ;
33+ }
Original file line number Diff line number Diff line change 1+ // https://github.com/observablehq/notebook-kit/blob/main/src/runtime/stdlib/generators/observe.ts
2+
3+ export async function * observe ( initialize ) {
4+ let resolve = undefined ;
5+ let value = undefined ;
6+ let stale = false ;
7+
8+ const dispose = initialize ( ( x ) => {
9+ value = x ;
10+ if ( resolve ) {
11+ resolve ( x ) ;
12+ resolve = undefined ;
13+ } else {
14+ stale = true ;
15+ }
16+ return x ;
17+ } ) ;
18+
19+ if ( dispose != null && typeof dispose !== "function" ) {
20+ throw new Error (
21+ typeof dispose === "object" && "then" in dispose && typeof dispose . then === "function"
22+ ? "async initializers are not supported"
23+ : "initializer returned something, but not a dispose function" ,
24+ ) ;
25+ }
26+
27+ try {
28+ while ( true ) {
29+ yield stale ? ( ( stale = false ) , value ) : new Promise ( ( _ ) => ( resolve = _ ) ) ;
30+ }
31+ } finally {
32+ if ( dispose != null ) {
33+ dispose ( ) ;
34+ }
35+ }
36+ }
Original file line number Diff line number Diff line change @@ -14,3 +14,4 @@ export {mandelbrotSet} from "./mandelbrot-set.js";
1414export { matrixRain } from "./matrix-rain.js" ;
1515export { jsDocString } from "./js-doc-string.js" ;
1616export { commentLink } from "./comment-link.js" ;
17+ export { mutable } from "./mutable.js" ;
Original file line number Diff line number Diff line change 1+ export const mutable = `const {a, getA, setA} = (() => {
2+ const a = Mutable(0);
3+ return {a, getA: () => a.value, setA: (value) => a.value = value};
4+ })();
5+
6+ setA(a + 1);
7+
8+ echo(a);` ;
9+
10+ // export const mutable = `const {a, getA, setA} = (() => {
11+ // const a = Mutable(0);
12+ // return {a, getA: () => a.value, setA: (value) => a.value = value};
13+ // })();
14+
15+ // setA(getA() + 1);
16+
17+ // echo(a);`;
You can’t perform that action at this time.
0 commit comments