1
- import type { Variable , VariableDefinition } from "@observablehq/runtime" ;
1
+ import { Runtime , type Module , type Variable , type VariableDefinition } from "@observablehq/runtime" ;
2
2
import type { DisplayState } from "./display.js" ;
3
3
import { clear , display , observe } from "./display.js" ;
4
- import { main } from "./index.js" ;
4
+ import { library } from "./stdlib /index.js" ;
5
5
import { input } from "./stdlib/generators/index.js" ;
6
6
import { Mutator } from "./stdlib/mutable.js" ;
7
+ import { fileAttachments } from "./stdlib/fileAttachment.js" ;
7
8
8
9
export type DefineState = DisplayState & {
9
10
/** the runtime variables associated with this cell */
@@ -31,61 +32,87 @@ export type Definition = {
31
32
assets ?: Map < string , string > ;
32
33
} ;
33
34
34
- export function define ( state : DefineState , definition : Definition , observer = observe ) : void {
35
- const { id, body, inputs = [ ] , outputs = [ ] , output, autodisplay, autoview, automutable} = definition ;
36
- const variables = state . variables ;
37
- const v = main . variable ( observer ( state , definition ) , { shadow : { } } ) ;
38
- const vid = output ?? ( outputs . length ? `cell ${ id } ` : null ) ;
39
- if ( inputs . includes ( "display" ) || inputs . includes ( "view" ) ) {
40
- let displayVersion = - 1 ; // the variable._version of currently-displayed values
41
- const vd = new ( v . constructor as typeof Variable ) ( 2 , v . _module ) ;
42
- vd . define (
43
- inputs . filter ( ( i ) => i !== "display" && i !== "view" ) ,
44
- ( ) => {
45
- const version = v . _version ; // capture version on input change
46
- return ( value : unknown ) => {
47
- if ( version < displayVersion ) throw new Error ( "stale display" ) ;
48
- else if ( state . variables [ 0 ] !== v ) throw new Error ( "stale display" ) ;
49
- else if ( version > displayVersion ) clear ( state ) ;
50
- displayVersion = version ;
51
- display ( state , value ) ;
52
- return value ;
53
- } ;
54
- }
55
- ) ;
56
- v . _shadow . set ( "display" , vd ) ;
57
- if ( inputs . includes ( "view" ) ) {
58
- const vv = new ( v . constructor as typeof Variable ) ( 2 , v . _module , null , { shadow : { } } ) ;
59
- vv . _shadow . set ( "display" , vd ) ;
60
- vv . define ( [ "display" ] , ( display ) => ( value : unknown ) => input ( display ( value ) ) ) ;
61
- v . _shadow . set ( "view" , vv ) ;
62
- }
63
- } else if ( ! autodisplay ) {
64
- clear ( state ) ;
35
+ export class NotebookInstance {
36
+
37
+ readonly runtime = Object . assign ( new Runtime ( { ...library , __ojs_runtime : ( ) => this . runtime } ) , { fileAttachments } ) ;
38
+ readonly main = ( this . runtime as typeof this . runtime & { main : Module } ) . main = this . runtime . module ( ) ;
39
+
40
+ constructor ( ) {
65
41
}
66
- variables . push ( v . define ( vid , inputs , body ) ) ;
67
- if ( output != null ) {
68
- if ( autoview ) {
69
- const o = unprefix ( output , "viewof$" ) ;
70
- variables . push ( main . define ( o , [ output ] , input ) ) ;
71
- } else if ( automutable ) {
72
- const o = unprefix ( output , "mutable " ) ;
73
- const x = `cell ${ id } ` ;
74
- v . define ( o , [ x ] , ( [ mutable ] ) => mutable ) ; // observe live value
75
- variables . push (
76
- main . define ( output , inputs , body ) , // initial value
77
- main . define ( x , [ output ] , Mutator ) ,
78
- main . define ( `mutable$${ o } ` , [ x ] , ( [ , mutator ] ) => mutator )
42
+
43
+ define ( state : DefineState , definition : Definition , observer = observe ) : void {
44
+ const { id, body, inputs = [ ] , outputs = [ ] , output, autodisplay, autoview, automutable } = definition ;
45
+ const variables = state . variables ;
46
+ const v = this . main . variable ( observer ( state , definition ) , { shadow : { } } ) ;
47
+ const vid = output ?? ( outputs . length ? `cell ${ id } ` : null ) ;
48
+ if ( inputs . includes ( "display" ) || inputs . includes ( "view" ) ) {
49
+ let displayVersion = - 1 ; // the variable._version of currently-displayed values
50
+ const vd = new ( v . constructor as typeof Variable ) ( 2 , v . _module ) ;
51
+ vd . define (
52
+ inputs . filter ( ( i ) => i !== "display" && i !== "view" ) ,
53
+ ( ) => {
54
+ const version = v . _version ; // capture version on input change
55
+ return ( value : unknown ) => {
56
+ if ( version < displayVersion ) throw new Error ( "stale display" ) ;
57
+ else if ( state . variables [ 0 ] !== v ) throw new Error ( "stale display" ) ;
58
+ else if ( version > displayVersion ) clear ( state ) ;
59
+ displayVersion = version ;
60
+ display ( state , value ) ;
61
+ return value ;
62
+ } ;
63
+ }
79
64
) ;
65
+ v . _shadow . set ( "display" , vd ) ;
66
+ if ( inputs . includes ( "view" ) ) {
67
+ const vv = new ( v . constructor as typeof Variable ) ( 2 , v . _module , null , { shadow : { } } ) ;
68
+ vv . _shadow . set ( "display" , vd ) ;
69
+ vv . define ( [ "display" ] , ( display ) => ( value : unknown ) => input ( display ( value ) ) ) ;
70
+ v . _shadow . set ( "view" , vv ) ;
71
+ }
72
+ } else if ( ! autodisplay ) {
73
+ clear ( state ) ;
80
74
}
81
- } else {
82
- for ( const o of outputs ) {
83
- variables . push ( main . variable ( true ) . define ( o , [ vid ! ] , ( exports ) => exports [ o ] ) ) ;
75
+ variables . push ( v . define ( vid , inputs , body ) ) ;
76
+ if ( output != null ) {
77
+ if ( autoview ) {
78
+ const o = this . unprefix ( output , "viewof$" ) ;
79
+ variables . push ( this . main . define ( o , [ output ] , input ) ) ;
80
+ } else if ( automutable ) {
81
+ const o = this . unprefix ( output , "mutable " ) ;
82
+ const x = `cell ${ id } ` ;
83
+ v . define ( o , [ x ] , ( [ mutable ] ) => mutable ) ; // observe live value
84
+ variables . push (
85
+ this . main . define ( output , inputs , body ) , // initial value
86
+ this . main . define ( x , [ output ] , Mutator ) ,
87
+ this . main . define ( `mutable$${ o } ` , [ x ] , ( [ , mutator ] ) => mutator )
88
+ ) ;
89
+ }
90
+ } else {
91
+ for ( const o of outputs ) {
92
+ variables . push ( this . main . variable ( true ) . define ( o , [ vid ! ] , ( exports ) => exports [ o ] ) ) ;
93
+ }
84
94
}
85
95
}
86
- }
87
96
88
- function unprefix ( name : string , prefix : string ) : string {
89
- if ( ! name . startsWith ( prefix ) ) throw new Error ( `expected ${ prefix } : ${ name } ` ) ;
90
- return name . slice ( prefix . length ) ;
97
+ protected unprefix ( name : string , prefix : string ) : string {
98
+ if ( ! name . startsWith ( prefix ) ) throw new Error ( `expected ${ prefix } : ${ name } ` ) ;
99
+ return name . slice ( prefix . length ) ;
100
+ }
91
101
}
102
+
103
+ const defaultInstance = new NotebookInstance ( ) ;
104
+
105
+ export const runtime = defaultInstance . runtime ;
106
+ export const main = defaultInstance . main ;
107
+
108
+ main . constructor . prototype . defines = function ( this : Module , name : string ) : boolean {
109
+ return (
110
+ this . _scope . has ( name ) ||
111
+ this . _builtins . has ( name ) ||
112
+ this . _runtime . _builtin . _scope . has ( name )
113
+ ) ;
114
+ } ;
115
+
116
+ export function define ( state : DefineState , definition : Definition , observer = observe ) : void {
117
+ defaultInstance . define ( state , definition , observer ) ;
118
+ }
0 commit comments