@vizhub/runtime 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +173 -0
  2. package/package.json +37 -0
  3. package/src/computeSrcDoc.ts +68 -0
  4. package/src/index.ts +7 -0
  5. package/src/useRuntime.ts +394 -0
  6. package/src/v2Runtime/bundle/bubleJSXOnly.ts +34 -0
  7. package/src/v2Runtime/bundle/getLibraries.js +31 -0
  8. package/src/v2Runtime/bundle/hypothetical.js +232 -0
  9. package/src/v2Runtime/bundle/index.js +88 -0
  10. package/src/v2Runtime/bundle/packageJson.ts +49 -0
  11. package/src/v2Runtime/bundle/rollup.browser.js +28414 -0
  12. package/src/v2Runtime/bundle.test.js +151 -0
  13. package/src/v2Runtime/computeSrcDocV2.test.ts +163 -0
  14. package/src/v2Runtime/computeSrcDocV2.ts +34 -0
  15. package/src/v2Runtime/getComputedIndexHtml.test.ts +33 -0
  16. package/src/v2Runtime/getComputedIndexHtml.ts +106 -0
  17. package/src/v2Runtime/getText.ts +19 -0
  18. package/src/v2Runtime/magicSandbox.js +291 -0
  19. package/src/v2Runtime/packageJson.js +42 -0
  20. package/src/v2Runtime/transformFiles.test.js +18 -0
  21. package/src/v2Runtime/transformFiles.ts +15 -0
  22. package/src/v2Runtime/v3FilesToV2Files.test.ts +20 -0
  23. package/src/v2Runtime/v3FilesToV2Files.ts +14 -0
  24. package/src/v3Runtime/build.test.ts +474 -0
  25. package/src/v3Runtime/build.ts +270 -0
  26. package/src/v3Runtime/cleanRollupErrorMessage.ts +15 -0
  27. package/src/v3Runtime/computeSrcDocV3.ts +151 -0
  28. package/src/v3Runtime/extractVizImport.test.ts +41 -0
  29. package/src/v3Runtime/extractVizImport.ts +34 -0
  30. package/src/v3Runtime/generateRollupErrorMessage.ts +84 -0
  31. package/src/v3Runtime/importFromViz.ts +36 -0
  32. package/src/v3Runtime/index.ts +1 -0
  33. package/src/v3Runtime/parseId.ts +14 -0
  34. package/src/v3Runtime/setupV3Runtime.ts +478 -0
  35. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/bundle-modified-src.js +121 -0
  36. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/bundle-modified.js +121 -0
  37. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/bundle.js +239 -0
  38. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/index.js +1 -0
  39. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/package-lock.json +475 -0
  40. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/package.json +19 -0
  41. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/rollup.config.js +9 -0
  42. package/src/v3Runtime/transformDSV/index.ts +71 -0
  43. package/src/v3Runtime/transformSvelte.ts +111 -0
  44. package/src/v3Runtime/types.ts +158 -0
  45. package/src/v3Runtime/urlLoad.ts +33 -0
  46. package/src/v3Runtime/virtual.ts +27 -0
  47. package/src/v3Runtime/vizCache.test.ts +126 -0
  48. package/src/v3Runtime/vizCache.ts +60 -0
  49. package/src/v3Runtime/vizLoad.ts +68 -0
  50. package/src/v3Runtime/vizLoadSvelte.ts +46 -0
  51. package/src/v3Runtime/vizResolve.ts +100 -0
  52. package/src/v3Runtime/worker.ts +231 -0
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # @vizhub-core/runtime
2
+
3
+ The `@vizhub-core/runtime` package is a core component of the VizHub platform, responsible for executing and rendering visualizations in an isolated environment. It supports multiple runtime versions (V2 and V3) and provides a flexible system for handling dependencies, file transformations, and hot reloading.
4
+
5
+ ## Features
6
+
7
+ - **Multi-version runtime support**: Supports both V2 and V3 runtime environments, allowing for backward compatibility and future-proofing.
8
+ - **Hot reloading**: Automatically reloads visualizations when files are updated, providing a smooth development experience.
9
+ - **Dependency management**: Handles external dependencies via CDN and supports custom package configurations.
10
+ - **File transformations**: Transforms various file types (e.g., JavaScript, CSS, CSV, Svelte) to be used in the runtime environment.
11
+ - **Virtual file system**: Implements a virtual file system for handling imports and file loading within the runtime.
12
+ - **Web Worker-based build system**: Uses Web Workers to offload the build process, ensuring a responsive UI during development.
13
+
14
+ ## Installation
15
+
16
+ Install the package using npm:
17
+
18
+ ```bash
19
+ npm install @vizhub-core/runtime
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ The `@vizhub-core/runtime` package is designed to be used within the VizHub platform but can also be utilized in other environments where isolated execution of visualizations is required.
25
+
26
+ ### Example
27
+
28
+ Here's an example of how to use the runtime to compute the `srcdoc` for a visualization:
29
+
30
+ ```javascript
31
+ import { computeSrcDoc } from '@vizhub-core/runtime';
32
+ import { rollup } from 'rollup';
33
+ import { createVizCache } from '@vizhub-core/runtime/v3Runtime/vizCache';
34
+
35
+ const vizCache = createVizCache({
36
+ initialContents: [],
37
+ handleCacheMiss: async (vizId) => {
38
+ // Fetch the content for the vizId
39
+ },
40
+ });
41
+
42
+ const content = {
43
+ id: 'example-viz',
44
+ files: {
45
+ 'index.js': {
46
+ name: 'index.js',
47
+ text: 'console.log("Hello World");',
48
+ },
49
+ 'index.html': {
50
+ name: 'index.html',
51
+ text: '<html><body><h1>Hello World</h1></body></html>',
52
+ },
53
+ },
54
+ };
55
+
56
+ const { initialSrcdoc, initialSrcdocError } =
57
+ await computeSrcDoc({
58
+ rollup,
59
+ content,
60
+ vizCache,
61
+ resolveSlug: async ({ userName, slug }) => {
62
+ // Resolve slug to vizId
63
+ },
64
+ getSvelteCompiler: async () => {
65
+ // Return the Svelte compiler
66
+ },
67
+ });
68
+
69
+ if (initialSrcdocError) {
70
+ console.error(
71
+ 'Error computing srcdoc:',
72
+ initialSrcdocError,
73
+ );
74
+ } else {
75
+ console.log('Computed srcdoc:', initialSrcdoc);
76
+ }
77
+ ```
78
+
79
+ ## API Documentation
80
+
81
+ ### `computeSrcDoc`
82
+
83
+ Computes the `srcdoc` for a visualization based on its content and dependencies.
84
+
85
+ #### Parameters
86
+
87
+ - **`rollup`**: The Rollup instance used for bundling.
88
+ - **`content`**: The content of the visualization, including files like `index.js` and `index.html`.
89
+ - **`vizCache`**: A cache of visualizations used to resolve imports from other visualizations.
90
+ - **`resolveSlug`**: A function to resolve slug-based imports to a viz ID.
91
+ - **`getSvelteCompiler`**: A function to get the Svelte compiler.
92
+
93
+ #### Returns
94
+
95
+ A promise that resolves to an object containing:
96
+
97
+ - **`initialSrcdoc`**: The computed `srcdoc` for the visualization.
98
+ - **`initialSrcdocError`**: Any error that occurred during the computation.
99
+
100
+ ### `createVizCache`
101
+
102
+ Creates a cache for visualizations, used to resolve imports from other visualizations.
103
+
104
+ #### Parameters
105
+
106
+ - **`initialContents`**: An array of initial contents to populate the cache.
107
+ - **`handleCacheMiss`**: A function called when a visualization is not found in the cache.
108
+
109
+ #### Returns
110
+
111
+ A `VizCache` object with the following methods:
112
+
113
+ - **`get(vizId)`**: Retrieves the content of a visualization by its ID.
114
+ - **`set(content)`**: Adds or updates the content of a visualization in the cache.
115
+ - **`invalidate(vizId)`**: Invalidates the cache for a specific visualization.
116
+
117
+ ### `setJSDOM`
118
+
119
+ Sets the DOM parser for environments where the native `DOMParser` is not available (e.g., Node.js).
120
+
121
+ #### Parameters
122
+
123
+ - **`JSDOM`**: The `JSDOM` instance to use for parsing HTML.
124
+
125
+ ### `cleanRollupErrorMessage`
126
+
127
+ Cleans up Rollup error messages by removing unnecessary details like the viz ID.
128
+
129
+ #### Parameters
130
+
131
+ - **`rawMessage`**: The raw error message from Rollup.
132
+ - **`vizId`**: The ID of the visualization.
133
+
134
+ #### Returns
135
+
136
+ - A cleaned-up error message string.
137
+
138
+ ## Development
139
+
140
+ To contribute to the development of this package, follow these steps:
141
+
142
+ ### Clone the Repository
143
+
144
+ ```bash
145
+ git clone https://github.com/vizhub-core/vizhub3.git
146
+ cd vizhub3
147
+ ```
148
+
149
+ ### Install Dependencies
150
+
151
+ ```bash
152
+ npm install
153
+ ```
154
+
155
+ ### Run Tests
156
+
157
+ The package uses Vitest for testing. Run the tests with:
158
+
159
+ ```bash
160
+ npm run test
161
+ ```
162
+
163
+ ### Build the Package
164
+
165
+ To build the package, use:
166
+
167
+ ```bash
168
+ npm run build
169
+ ```
170
+
171
+ ## License
172
+
173
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@vizhub/runtime",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "src/index",
6
+ "scripts": {
7
+ "tsc": "tsc --noEmit",
8
+ "test": "vitest run --reporter verbose",
9
+ "prettier": "prettier {*.*,**/*.*} --single-quote --write"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/vizhub-core/vizhub3.git"
14
+ },
15
+ "author": "Curran Kelleher",
16
+ "license": "MIT",
17
+ "bugs": {
18
+ "url": "https://github.com/vizhub-core/vizhub3/issues"
19
+ },
20
+ "homepage": "https://github.com/vizhub-core/vizhub3#readme",
21
+ "dependencies": {
22
+ "d3-dsv": "^3.0.1",
23
+ "react": "^18.3.1",
24
+ "rollup": "^4.24.0",
25
+ "svelte": "^4.2.19"
26
+ },
27
+ "devDependencies": {
28
+ "@types/d3-dsv": "^3.0.7",
29
+ "i": "^0.3.7",
30
+ "npm": "^10.9.0",
31
+ "typescript": "^5.6.3",
32
+ "vitest": "^2.1.2"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }
@@ -0,0 +1,68 @@
1
+ // import { rollup } from 'rollup';
2
+ import {
3
+ Content,
4
+ VizId,
5
+ getRuntimeVersion,
6
+ } from 'entities';
7
+ import { computeSrcDocV2 } from './v2Runtime/computeSrcDocV2';
8
+ import { computeSrcDocV3 } from './v3Runtime/computeSrcDocV3';
9
+ import { build } from './v3Runtime/build';
10
+ import { VizCache } from './v3Runtime/vizCache';
11
+
12
+ const debug = false;
13
+ export const computeSrcDoc = async ({
14
+ rollup,
15
+ content,
16
+ vizCache,
17
+ resolveSlug,
18
+ getSvelteCompiler,
19
+ }: {
20
+ rollup: any;
21
+ content: Content;
22
+ vizCache: VizCache;
23
+ // Resolves a slug import to a viz ID.
24
+ resolveSlug: ({ userName, slug }) => Promise<VizId>;
25
+ getSvelteCompiler: () => Promise<any>;
26
+ }) => {
27
+ // `runtimeVersion` is used to determine which runtime
28
+ // to use. It's either 2 or 3.
29
+ const runtimeVersion: number = getRuntimeVersion(content);
30
+
31
+ let initialSrcdoc = '';
32
+ let initialSrcdocError: string | null = null;
33
+
34
+ if (debug) {
35
+ console.log('computeSrcDoc.ts: computeSrcDoc()');
36
+ console.log(' runtimeVersion:', runtimeVersion);
37
+ console.log(' content:', content);
38
+ }
39
+
40
+ try {
41
+ if (runtimeVersion === 2) {
42
+ initialSrcdoc = await computeSrcDocV2(content);
43
+ } else if (runtimeVersion === 3) {
44
+ const buildResult = await build({
45
+ vizId: content.id,
46
+ enableSourcemap: true,
47
+ rollup,
48
+ vizCache,
49
+ resolveSlug,
50
+ getSvelteCompiler,
51
+ });
52
+ initialSrcdoc = await computeSrcDocV3({
53
+ vizCache,
54
+ buildResult,
55
+ });
56
+ }
57
+ } catch (error) {
58
+ // initialSrcdocError = e.toString();
59
+ initialSrcdocError = error.message;
60
+ }
61
+
62
+ return {
63
+ // Escape ending tags in strings like "</script>",
64
+ // so that they don't break the HTML.
65
+ initialSrcdoc,
66
+ initialSrcdocError,
67
+ };
68
+ };
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export type { V3BuildResult } from './v3Runtime';
2
+ export type { VizCache } from './v3Runtime/vizCache';
3
+ export { computeSrcDoc } from './computeSrcDoc';
4
+ export { setJSDOM } from './v2Runtime/getComputedIndexHtml';
5
+ export { useRuntime } from './useRuntime';
6
+ export { createVizCache } from './v3Runtime/vizCache';
7
+ export { cleanRollupErrorMessage } from './v3Runtime/cleanRollupErrorMessage';
@@ -0,0 +1,394 @@
1
+ import {
2
+ RefObject,
3
+ useEffect,
4
+ useMemo,
5
+ useRef,
6
+ useCallback,
7
+ } from 'react';
8
+ import {
9
+ Content,
10
+ FileId,
11
+ SlugKey,
12
+ VizId,
13
+ generateFileId,
14
+ getRuntimeVersion,
15
+ } from 'entities';
16
+ import { V3Runtime } from './v3Runtime/setupV3Runtime';
17
+
18
+ const debug = false;
19
+
20
+ // Sets up either the v2 or v3 runtime environment.
21
+ // Meant to support dynamic switching between the two.
22
+ export const useRuntime = ({
23
+ content,
24
+ iframeRef,
25
+ srcdocErrorMessage,
26
+ setSrcdocErrorMessage,
27
+ vizCacheContents,
28
+ isVisual,
29
+ slugResolutionCache,
30
+ submitContentOperation,
31
+ }: {
32
+ content: Content;
33
+ iframeRef: RefObject<HTMLIFrameElement>;
34
+ srcdocErrorMessage: string | null;
35
+ setSrcdocErrorMessage: (error: string | null) => void;
36
+ vizCacheContents: Record<string, Content>;
37
+
38
+ // If this is false, there is no iframeRef.current.
39
+ isVisual: boolean;
40
+ slugResolutionCache: Record<SlugKey, VizId>;
41
+ submitContentOperation: (
42
+ next: (content: Content) => Content,
43
+ ) => void;
44
+ }) => {
45
+ // This ref is used to skip the first mount.
46
+ const initialMount = useRef(true);
47
+
48
+ // `runtimeVersion` is used to determine which runtime
49
+ // to use. It's either 2 or 3.
50
+ const runtimeVersion: number = useMemo(
51
+ () => getRuntimeVersion(content),
52
+ [content],
53
+ );
54
+
55
+ const v3RuntimeRef = useRef<V3Runtime | null>(null);
56
+
57
+ const getV3Runtime = useCallback(async () => {
58
+ if (v3RuntimeRef.current === null) {
59
+ // throw new Error('v3Runtime.current is null');
60
+ // Poll for this to be defined.
61
+ // const interval = setInterval(() => {
62
+ // if (debug) {
63
+ // console.log('polling for v3Runtime.current...');
64
+ // }
65
+ // if (v3RuntimeRef.current !== null) {
66
+ // clearInterval(interval);
67
+ // return v3RuntimeRef.current;
68
+ // }
69
+ // }, 100);
70
+ return new Promise<V3Runtime>((resolve) => {
71
+ const interval = setInterval(() => {
72
+ if (debug) {
73
+ console.log('polling for v3Runtime.current...');
74
+ }
75
+ if (v3RuntimeRef.current !== null) {
76
+ clearInterval(interval);
77
+ resolve(v3RuntimeRef.current);
78
+ }
79
+ }, 100);
80
+ });
81
+ }
82
+ return v3RuntimeRef.current;
83
+ }, []);
84
+
85
+ const vizCacheContentsRef = useRef(vizCacheContents);
86
+
87
+ useEffect(() => {
88
+ vizCacheContentsRef.current = vizCacheContents;
89
+ }, [vizCacheContents]);
90
+
91
+ // Handles cache misses for viz content,
92
+ // when a viz imports from another viz.
93
+ const getLatestContent = useCallback(
94
+ async (vizId: VizId): Promise<Content> => {
95
+ // Sanity check, should never happen.
96
+ if (!vizCacheContentsRef.current) {
97
+ throw new Error(
98
+ 'vizCacheContentsRef.current is null',
99
+ );
100
+ }
101
+
102
+ const content = vizCacheContentsRef.current[vizId];
103
+
104
+ // If the viz content for this import is already tracked,
105
+ // then return it.
106
+ if (content) {
107
+ return content;
108
+ } else {
109
+ // TODO make this happen by:
110
+ // * Fetching the viz content from the server
111
+ // * Using a new API endpoint that returns the viz content
112
+ // * Ingesting the snapshot and incorporating it into the vizCacheContents
113
+ throw new Error(
114
+ `TODO client-side fetching of newly imported vizzes. Current workaround: refresh the page`,
115
+ );
116
+ }
117
+ },
118
+ [],
119
+ );
120
+
121
+ // Handles cache misses for slug resolution,
122
+ // when a viz imports from another viz.
123
+ const resolveSlugKey = useCallback(
124
+ async (slugKey: SlugKey): Promise<VizId> => {
125
+ // Sanity check, should never happen.
126
+ if (!slugResolutionCache) {
127
+ throw new Error('slugResolutionCache is null');
128
+ }
129
+
130
+ const vizId = slugResolutionCache[slugKey];
131
+
132
+ // If the viz ID for this slug is already tracked,
133
+ // then return it.
134
+ if (vizId) {
135
+ return vizId;
136
+ } else {
137
+ // TODO make this happen by:
138
+ // * Resolving the slug from the server
139
+ // * Using a new API endpoint that returns the viz id for a slugKey
140
+ throw new Error(
141
+ `TODO client-side resolution of newly imported vizzes. Current workaround: refresh the page`,
142
+ );
143
+ }
144
+ },
145
+ [],
146
+ );
147
+
148
+ // Set up the v3 runtime.
149
+ // TODO QA the following:
150
+ // * Adding and removing index.js
151
+ // * Adding and removing index.html
152
+ // * Switching between versions of the runtime
153
+ useEffect(() => {
154
+ // If the viz is not visual (README.md only), then
155
+ // we don't need to set up the v3 runtime.
156
+ if (isVisual === false) {
157
+ return;
158
+ }
159
+ if (runtimeVersion === 3) {
160
+ // Load the v3 runtime.
161
+ import('./v3Runtime/setupV3Runtime').then(
162
+ ({ setupV3Runtime }) => {
163
+ const iframe = iframeRef.current;
164
+
165
+ // Should never happen. Added to pacify TypeScript.
166
+ if (iframe === null) {
167
+ throw new Error('iframe is null');
168
+ }
169
+
170
+ if (!content.id) {
171
+ throw new Error('content.id is not defined');
172
+ }
173
+
174
+ // Writes the content of a file.
175
+ const writeFile = (
176
+ name: string,
177
+ text: string,
178
+ ) => {
179
+ submitContentOperation((content: Content) => {
180
+ // For new files, generate a fileId.
181
+ let fileId: FileId = generateFileId();
182
+
183
+ // For existing files, get the fileId.
184
+ const { files } = content;
185
+ if (files !== undefined) {
186
+ const fileIds = Object.keys(files);
187
+ const foundFileId = fileIds.find(
188
+ (fileId) => files[fileId].name === name,
189
+ );
190
+ if (foundFileId) {
191
+ fileId = foundFileId;
192
+ }
193
+ }
194
+
195
+ return {
196
+ ...content,
197
+ files: {
198
+ ...content.files,
199
+ [fileId]: {
200
+ name,
201
+ text,
202
+ },
203
+ },
204
+ // Trigger a re-run.
205
+ isInteracting: true,
206
+ };
207
+ });
208
+
209
+ // Clear the `isInteracting` property.
210
+ setTimeout(() => {
211
+ // This somewhat cryptic logic
212
+ // deletes the `isInteracting` property
213
+ // from the document.
214
+ submitContentOperation(
215
+ ({ isInteracting, ...newDocument }) =>
216
+ newDocument,
217
+ );
218
+ }, 0);
219
+ };
220
+
221
+ v3RuntimeRef.current = setupV3Runtime({
222
+ vizId: content.id,
223
+ iframe,
224
+ setSrcdocErrorMessage,
225
+ getLatestContent,
226
+ resolveSlugKey,
227
+ writeFile,
228
+ });
229
+ },
230
+ );
231
+ }
232
+ }, [runtimeVersion, isVisual, submitContentOperation]);
233
+
234
+ // Send updates of imported vizzes to the V3 runtime.
235
+ const previousVizCacheContents = useRef(vizCacheContents);
236
+
237
+ // Track the srcdoc error message, but only check it
238
+ // when we are attempting to run (do not re-run when
239
+ // the error message changes or is cleared).
240
+ const srcdocErrorMessageRef = useRef(srcdocErrorMessage);
241
+ useEffect(() => {
242
+ srcdocErrorMessageRef.current = srcdocErrorMessage;
243
+ }, [srcdocErrorMessage]);
244
+
245
+ useEffect(() => {
246
+ // Don't crash for v2 runtime!
247
+ if (runtimeVersion !== 3) {
248
+ return;
249
+ }
250
+
251
+ // Don't run on first render.
252
+ if (initialMount.current === true) {
253
+ return;
254
+ }
255
+
256
+ // Don't run if the viz is not visual (README.md only).
257
+ if (isVisual === false) {
258
+ return;
259
+ }
260
+
261
+ // console.log(
262
+ // 'TODO update the v3 runtime when imported vizzes change',
263
+ // );
264
+
265
+ // Find the imported vizzes that have changed.
266
+ const changedVizIds = Object.keys(
267
+ vizCacheContents,
268
+ ).filter((vizId) => {
269
+ return (
270
+ previousVizCacheContents.current[vizId] !==
271
+ vizCacheContents[vizId]
272
+ );
273
+ });
274
+ previousVizCacheContents.current = vizCacheContents;
275
+
276
+ if (debug) {
277
+ console.log(
278
+ '[useRuntime] changedVizIds',
279
+ changedVizIds,
280
+ );
281
+ }
282
+
283
+ if (changedVizIds.length === 0) {
284
+ return;
285
+ }
286
+
287
+ // // See if any of the vizzes we import from are interacting.
288
+ let isInteracting = false;
289
+ for (const vizId of changedVizIds) {
290
+ if (vizCacheContents[vizId].isInteracting) {
291
+ isInteracting = true;
292
+ break;
293
+ }
294
+ }
295
+ if (debug) {
296
+ console.log('isInteracting', isInteracting);
297
+ }
298
+
299
+ const update = async () => {
300
+ const v3Runtime = await getV3Runtime();
301
+ // Sanity check, should never happen.
302
+ if (v3Runtime === null) {
303
+ throw new Error('v3Runtime is null');
304
+ }
305
+ if (isInteracting) {
306
+ // console.log('Running the code!');
307
+ // console.log(
308
+ // 'srcdocErrorMessageRef.current',
309
+ // srcdocErrorMessageRef.current,
310
+ // );
311
+
312
+ // If we are recovering from an error,
313
+ // clear the error message, and run the code
314
+ // totally fresh by re-computing the srcdoc.
315
+ if (srcdocErrorMessageRef.current) {
316
+ v3Runtime.resetSrcdoc(changedVizIds);
317
+ // try {
318
+ // const srcdoc = await computeSrcDocV3(content);
319
+ // if (iframeRef.current) {
320
+ // iframeRef.current.srcdoc = srcdoc;
321
+ // }
322
+ // } catch (error) {
323
+ // console.error(error);
324
+ // setSrcdocErrorMessage(error.message);
325
+ // }
326
+ } else {
327
+ // Re-run the code with hot reloading.
328
+ v3Runtime.invalidateVizCache(changedVizIds);
329
+ }
330
+ }
331
+ };
332
+ update();
333
+ }, [vizCacheContents, runtimeVersion]);
334
+
335
+ // Compute V2 updates on the main thread.
336
+ useEffect(() => {
337
+ // We don't need to execute a "run" on first render,
338
+ // because SSR handles the initial run by injecting
339
+ // the srcdoc into the page server-side.
340
+ if (initialMount.current) {
341
+ return;
342
+ }
343
+
344
+ // The following code only runs after the user
345
+ // has edited the code and the files have changed.
346
+ if (runtimeVersion === 2) {
347
+ // // Debounce the updates.
348
+ const v2Run = async () => {
349
+ // Clear the console before each run.
350
+ console.clear();
351
+
352
+ // Clear out the old error.
353
+ setSrcdocErrorMessage(null);
354
+
355
+ // v2RuntimeWorker.current.postMessage({ content });
356
+
357
+ // Set process on global scope so computeSrcDoc doesn't break.
358
+ // @ts-ignore
359
+ globalThis.process = {};
360
+
361
+ // Lazy load computeSrcDoc because it's a large chunk.
362
+ const { computeSrcDocV2 } = await import(
363
+ './v2Runtime/computeSrcDocV2'
364
+ );
365
+
366
+ // console.log(computeSrcDoc);
367
+ try {
368
+ const srcdoc = await computeSrcDocV2(content);
369
+ if (iframeRef.current) {
370
+ iframeRef.current.srcdoc = srcdoc;
371
+ }
372
+ } catch (error) {
373
+ console.error(error);
374
+ setSrcdocErrorMessage(error.message);
375
+ }
376
+ };
377
+ if (content.isInteracting) {
378
+ v2Run();
379
+ }
380
+ }
381
+ }, [
382
+ content.files,
383
+ content.isInteracting,
384
+ runtimeVersion,
385
+ ]);
386
+
387
+ // Track the initial mount.
388
+ useEffect(() => {
389
+ if (initialMount.current) {
390
+ initialMount.current = false;
391
+ return;
392
+ }
393
+ }, []);
394
+ };