@dxos/plugin-script 0.8.4-main.e098934 → 0.8.4-main.ead640a
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.
- package/dist/lib/browser/DeploymentDialog-65TWT6S5.mjs +13 -0
- package/dist/lib/browser/NotebookContainer-LVGRPFY3.mjs +683 -0
- package/dist/lib/browser/NotebookContainer-LVGRPFY3.mjs.map +7 -0
- package/dist/lib/browser/ScriptContainer-LRTRN7JW.mjs +149 -0
- package/dist/lib/browser/ScriptContainer-LRTRN7JW.mjs.map +7 -0
- package/dist/lib/browser/{app-graph-builder-IABOSTBK.mjs → app-graph-builder-DPYULSME.mjs} +8 -7
- package/dist/lib/browser/app-graph-builder-DPYULSME.mjs.map +7 -0
- package/dist/lib/browser/{blueprint-definition-AR7ITBCD.mjs → blueprint-definition-ET5KZ46I.mjs} +3 -3
- package/dist/lib/browser/{blueprint-definition-AR7ITBCD.mjs.map → blueprint-definition-ET5KZ46I.mjs.map} +1 -1
- package/dist/lib/browser/chunk-5CYLWXRH.mjs +89 -0
- package/dist/lib/browser/chunk-5CYLWXRH.mjs.map +7 -0
- package/dist/lib/browser/chunk-75LH4EUR.mjs +326 -0
- package/dist/lib/browser/chunk-75LH4EUR.mjs.map +7 -0
- package/dist/lib/browser/{chunk-6CAH7VIE.mjs → chunk-E7DXDICD.mjs} +18 -19
- package/dist/lib/browser/chunk-E7DXDICD.mjs.map +7 -0
- package/dist/lib/browser/{chunk-QYAREHGH.mjs → chunk-EZVXV6DA.mjs} +3 -5
- package/dist/lib/browser/chunk-EZVXV6DA.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GZKWMME3.mjs → chunk-I3QSGUFJ.mjs} +122 -32
- package/dist/lib/browser/chunk-I3QSGUFJ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-NXKU3BNX.mjs → chunk-JO2O7W6J.mjs} +39 -7
- package/dist/lib/browser/chunk-JO2O7W6J.mjs.map +7 -0
- package/dist/lib/browser/chunk-N6M34EUC.mjs +112 -0
- package/dist/lib/browser/chunk-N6M34EUC.mjs.map +7 -0
- package/dist/lib/browser/{chunk-YCZPTTFO.mjs → chunk-NM4WQS4F.mjs} +14 -14
- package/dist/lib/browser/chunk-NM4WQS4F.mjs.map +7 -0
- package/dist/lib/browser/{chunk-5TVBECWH.mjs → chunk-OKXN2N7M.mjs} +2 -2
- package/dist/lib/browser/chunk-ST3ACVUC.mjs +88 -0
- package/dist/lib/browser/chunk-ST3ACVUC.mjs.map +7 -0
- package/dist/lib/browser/{compiler-2HJH34GM.mjs → compiler-G2N2CG63.mjs} +5 -5
- package/dist/lib/browser/{compiler-2HJH34GM.mjs.map → compiler-G2N2CG63.mjs.map} +1 -1
- package/dist/lib/browser/index.mjs +107 -36
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-F4YSRPJI.mjs → intent-resolver-JLU7DVLQ.mjs} +31 -15
- package/dist/lib/browser/intent-resolver-JLU7DVLQ.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-BBHFU6MI.mjs → react-surface-76SDTUYG.mjs} +36 -13
- package/dist/lib/browser/react-surface-76SDTUYG.mjs.map +7 -0
- package/dist/lib/browser/{settings-KCTBK5TY.mjs → settings-ERFKVNUK.mjs} +9 -8
- package/dist/lib/browser/settings-ERFKVNUK.mjs.map +7 -0
- package/dist/lib/browser/templates/index.mjs +1 -1
- package/dist/lib/browser/types/index.mjs +7 -4
- package/dist/lib/node-esm/{DeploymentDialog-G6EHEPXN.mjs → DeploymentDialog-I63ZC2HH.mjs} +6 -5
- package/dist/lib/node-esm/NotebookContainer-QY5NJGJI.mjs +684 -0
- package/dist/lib/node-esm/NotebookContainer-QY5NJGJI.mjs.map +7 -0
- package/dist/lib/node-esm/ScriptContainer-SVXCSLNH.mjs +150 -0
- package/dist/lib/node-esm/ScriptContainer-SVXCSLNH.mjs.map +7 -0
- package/dist/lib/node-esm/{app-graph-builder-CQTTAYHP.mjs → app-graph-builder-UXJGHXSL.mjs} +8 -7
- package/dist/lib/node-esm/app-graph-builder-UXJGHXSL.mjs.map +7 -0
- package/dist/lib/node-esm/{blueprint-definition-TJY4TX6S.mjs → blueprint-definition-AIYFOT7Q.mjs} +3 -3
- package/dist/lib/node-esm/{blueprint-definition-TJY4TX6S.mjs.map → blueprint-definition-AIYFOT7Q.mjs.map} +1 -1
- package/dist/lib/node-esm/chunk-2GVTWESW.mjs +90 -0
- package/dist/lib/node-esm/chunk-2GVTWESW.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-4X375PGY.mjs +90 -0
- package/dist/lib/node-esm/chunk-4X375PGY.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-67OVZHI3.mjs +327 -0
- package/dist/lib/node-esm/chunk-67OVZHI3.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ZA36GO4T.mjs → chunk-C2ORIPKH.mjs} +14 -14
- package/dist/lib/node-esm/chunk-C2ORIPKH.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-35M3CHYE.mjs → chunk-NUXZQQ6P.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-AHXJ6NQU.mjs → chunk-OG2SIKHE.mjs} +3 -5
- package/dist/lib/node-esm/chunk-OG2SIKHE.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-HUHVIOL5.mjs → chunk-SMFPSKQT.mjs} +122 -32
- package/dist/lib/node-esm/chunk-SMFPSKQT.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-VRSDE4CI.mjs +114 -0
- package/dist/lib/node-esm/chunk-VRSDE4CI.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-2GBESIHU.mjs → chunk-VZAFGLD7.mjs} +18 -19
- package/dist/lib/node-esm/chunk-VZAFGLD7.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-M642JUOZ.mjs → chunk-YW36TZ7K.mjs} +39 -7
- package/dist/lib/node-esm/chunk-YW36TZ7K.mjs.map +7 -0
- package/dist/lib/node-esm/{compiler-7SP27RA6.mjs → compiler-PLDAZ5GJ.mjs} +5 -5
- package/dist/lib/node-esm/{compiler-7SP27RA6.mjs.map → compiler-PLDAZ5GJ.mjs.map} +1 -1
- package/dist/lib/node-esm/index.mjs +107 -36
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-CGQYRWWD.mjs → intent-resolver-SFGTIFOG.mjs} +31 -15
- package/dist/lib/node-esm/intent-resolver-SFGTIFOG.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-UWIWPKZD.mjs → react-surface-SHEBNW4R.mjs} +36 -13
- package/dist/lib/node-esm/react-surface-SHEBNW4R.mjs.map +7 -0
- package/dist/lib/node-esm/{settings-DXZ334A3.mjs → settings-5TYXQ42N.mjs} +9 -8
- package/dist/lib/node-esm/settings-5TYXQ42N.mjs.map +7 -0
- package/dist/lib/node-esm/templates/index.mjs +1 -1
- package/dist/lib/node-esm/types/index.mjs +7 -4
- package/dist/types/src/ScriptPlugin.d.ts +1 -1
- package/dist/types/src/ScriptPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/DeploymentDialog/DeploymentDialog.d.ts +1 -1
- package/dist/types/src/components/DeploymentDialog/DeploymentDialog.d.ts.map +1 -1
- package/dist/types/src/components/DeploymentDialog/DeploymentDialog.stories.d.ts +111 -5
- package/dist/types/src/components/DeploymentDialog/DeploymentDialog.stories.d.ts.map +1 -1
- package/dist/types/src/components/NotebookContainer.d.ts +10 -0
- package/dist/types/src/components/NotebookContainer.d.ts.map +1 -0
- package/dist/types/src/components/NotebookContainer.stories.d.ts +248 -0
- package/dist/types/src/components/NotebookContainer.stories.d.ts.map +1 -0
- package/dist/types/src/components/NotebookStack/NotebookCell.d.ts +14 -0
- package/dist/types/src/components/NotebookStack/NotebookCell.d.ts.map +1 -0
- package/dist/types/src/components/NotebookStack/NotebookMenu.d.ts +9 -0
- package/dist/types/src/components/NotebookStack/NotebookMenu.d.ts.map +1 -0
- package/dist/types/src/components/NotebookStack/NotebookStack.d.ts +14 -0
- package/dist/types/src/components/NotebookStack/NotebookStack.d.ts.map +1 -0
- package/dist/types/src/components/NotebookStack/NotebookStack.stories.d.ts +248 -0
- package/dist/types/src/components/NotebookStack/NotebookStack.stories.d.ts.map +1 -0
- package/dist/types/src/components/NotebookStack/index.d.ts +3 -0
- package/dist/types/src/components/NotebookStack/index.d.ts.map +1 -0
- package/dist/types/src/components/ScriptContainer.d.ts +2 -2
- package/dist/types/src/components/ScriptContainer.d.ts.map +1 -1
- package/dist/types/src/components/ScriptToolbar/ScriptToolbar.d.ts.map +1 -1
- package/dist/types/src/components/ScriptToolbar/ScriptToolbar.stories.d.ts +239 -1
- package/dist/types/src/components/ScriptToolbar/ScriptToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/Settings/ScriptObjectSettings.d.ts.map +1 -1
- package/dist/types/src/components/Settings/ScriptPluginSettings.d.ts +2 -2
- package/dist/types/src/components/Settings/ScriptPluginSettings.d.ts.map +1 -1
- package/dist/types/src/components/TypescriptEditor/TypescriptEditor.d.ts +4 -2
- package/dist/types/src/components/TypescriptEditor/TypescriptEditor.d.ts.map +1 -1
- package/dist/types/src/components/TypescriptEditor/TypescriptEditor.stories.d.ts +3 -3
- package/dist/types/src/components/TypescriptEditor/TypescriptEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/hooks/deploy.d.ts +6 -6
- package/dist/types/src/hooks/deploy.d.ts.map +1 -1
- package/dist/types/src/hooks/template.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +0 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/notebook/eval.d.ts +13 -0
- package/dist/types/src/notebook/eval.d.ts.map +1 -0
- package/dist/types/src/notebook/index.d.ts +2 -0
- package/dist/types/src/notebook/index.d.ts.map +1 -0
- package/dist/types/src/notebook/notebook.d.ts +35 -0
- package/dist/types/src/notebook/notebook.d.ts.map +1 -0
- package/dist/types/src/notebook/notebook.test.d.ts +2 -0
- package/dist/types/src/notebook/notebook.test.d.ts.map +1 -0
- package/dist/types/src/notebook/vfs-parser.d.ts +74 -0
- package/dist/types/src/notebook/vfs-parser.d.ts.map +1 -0
- package/dist/types/src/notebook/vfs-parser.test.d.ts +2 -0
- package/dist/types/src/notebook/vfs-parser.test.d.ts.map +1 -0
- package/dist/types/src/templates/chess.d.ts.map +1 -1
- package/dist/types/src/templates/data-generator.d.ts.map +1 -1
- package/dist/types/src/templates/discord.d.ts.map +1 -1
- package/dist/types/src/templates/forex-effect.d.ts.map +1 -1
- package/dist/types/src/templates/forex.d.ts.map +1 -1
- package/dist/types/src/templates/gmail.d.ts.map +1 -1
- package/dist/types/src/templates/index.d.ts +43 -1
- package/dist/types/src/templates/index.d.ts.map +1 -1
- package/dist/types/src/templates/{echo.d.ts → ping.d.ts} +1 -1
- package/dist/types/src/templates/ping.d.ts.map +1 -0
- package/dist/types/src/testing/data.d.ts +19 -0
- package/dist/types/src/testing/data.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +27 -2
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/actions.d.ts +66 -0
- package/dist/types/src/types/actions.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -0
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +54 -31
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/util/functions.d.ts +5 -2
- package/dist/types/src/util/functions.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +67 -63
- package/src/ScriptPlugin.tsx +93 -68
- package/src/capabilities/app-graph-builder.ts +4 -3
- package/src/capabilities/artifact-definition.ts +1 -1
- package/src/capabilities/intent-resolver.ts +14 -4
- package/src/capabilities/react-surface.tsx +17 -5
- package/src/capabilities/settings.ts +3 -3
- package/src/components/DeploymentDialog/DeploymentDialog.stories.tsx +6 -4
- package/src/components/DeploymentDialog/DeploymentDialog.tsx +11 -17
- package/src/components/NotebookContainer.stories.tsx +32 -0
- package/src/components/NotebookContainer.tsx +124 -0
- package/src/components/NotebookStack/NotebookCell.tsx +217 -0
- package/src/components/NotebookStack/NotebookMenu.tsx +47 -0
- package/src/components/NotebookStack/NotebookStack.stories.tsx +32 -0
- package/src/components/NotebookStack/NotebookStack.tsx +79 -0
- package/src/components/NotebookStack/index.ts +6 -0
- package/src/components/ScriptContainer.tsx +2 -2
- package/src/components/ScriptToolbar/ScriptToolbar.stories.tsx +17 -5
- package/src/components/ScriptToolbar/ScriptToolbar.tsx +21 -24
- package/src/components/Settings/ScriptObjectSettings.tsx +92 -8
- package/src/components/Settings/ScriptPluginSettings.tsx +4 -19
- package/src/components/TestPanel/TestPanel.tsx +5 -5
- package/src/components/TypescriptEditor/TypescriptEditor.stories.tsx +71 -16
- package/src/components/TypescriptEditor/TypescriptEditor.tsx +29 -24
- package/src/components/index.ts +3 -0
- package/src/events.ts +2 -2
- package/src/hooks/deploy.ts +8 -9
- package/src/hooks/format.ts +2 -2
- package/src/hooks/template.ts +4 -3
- package/src/hooks/useCreateAndDeployScriptTemplates.ts +3 -3
- package/src/index.ts +1 -0
- package/src/meta.ts +2 -4
- package/src/notebook/eval.ts +105 -0
- package/src/notebook/index.ts +5 -0
- package/src/notebook/notebook.test.ts +70 -0
- package/src/notebook/notebook.ts +183 -0
- package/src/notebook/vfs-parser.test.ts +149 -0
- package/src/notebook/vfs-parser.ts +451 -0
- package/src/templates/chess.ts +2 -0
- package/src/templates/data-generator.ts +2 -0
- package/src/templates/discord.ts +9 -1
- package/src/templates/forex-effect.ts +5 -1
- package/src/templates/forex.ts +2 -0
- package/src/templates/gmail.ts +21 -9
- package/src/templates/index.ts +6 -6
- package/src/testing/data.ts +47 -0
- package/src/testing/index.ts +5 -0
- package/src/translations.ts +30 -4
- package/src/types/actions.ts +53 -0
- package/src/types/index.ts +1 -0
- package/src/types/schema.ts +30 -19
- package/src/util/functions.ts +32 -3
- package/dist/lib/browser/DeploymentDialog-QZSTVNIS.mjs +0 -12
- package/dist/lib/browser/ScriptContainer-DNNA6XC6.mjs +0 -265
- package/dist/lib/browser/ScriptContainer-DNNA6XC6.mjs.map +0 -7
- package/dist/lib/browser/app-graph-builder-IABOSTBK.mjs.map +0 -7
- package/dist/lib/browser/chunk-6CAH7VIE.mjs.map +0 -7
- package/dist/lib/browser/chunk-GZKWMME3.mjs.map +0 -7
- package/dist/lib/browser/chunk-IS4OG2UW.mjs +0 -39
- package/dist/lib/browser/chunk-IS4OG2UW.mjs.map +0 -7
- package/dist/lib/browser/chunk-NXKU3BNX.mjs.map +0 -7
- package/dist/lib/browser/chunk-QYAREHGH.mjs.map +0 -7
- package/dist/lib/browser/chunk-RNGIQIEJ.mjs +0 -88
- package/dist/lib/browser/chunk-RNGIQIEJ.mjs.map +0 -7
- package/dist/lib/browser/chunk-YCZPTTFO.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-F4YSRPJI.mjs.map +0 -7
- package/dist/lib/browser/react-surface-BBHFU6MI.mjs.map +0 -7
- package/dist/lib/browser/settings-KCTBK5TY.mjs.map +0 -7
- package/dist/lib/node-esm/ScriptContainer-KPYZN2KY.mjs +0 -266
- package/dist/lib/node-esm/ScriptContainer-KPYZN2KY.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-CQTTAYHP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2GBESIHU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AHXJ6NQU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GWHLP5LM.mjs +0 -90
- package/dist/lib/node-esm/chunk-GWHLP5LM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HUHVIOL5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JIPFLBYA.mjs +0 -40
- package/dist/lib/node-esm/chunk-JIPFLBYA.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-M642JUOZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZA36GO4T.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-CGQYRWWD.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-UWIWPKZD.mjs.map +0 -7
- package/dist/lib/node-esm/settings-DXZ334A3.mjs.map +0 -7
- package/dist/types/src/templates/echo.d.ts.map +0 -1
- /package/dist/lib/browser/{DeploymentDialog-QZSTVNIS.mjs.map → DeploymentDialog-65TWT6S5.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-5TVBECWH.mjs.map → chunk-OKXN2N7M.mjs.map} +0 -0
- /package/dist/lib/node-esm/{DeploymentDialog-G6EHEPXN.mjs.map → DeploymentDialog-I63ZC2HH.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-35M3CHYE.mjs.map → chunk-NUXZQQ6P.mjs.map} +0 -0
- /package/src/templates/{echo.ts → ping.ts} +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { trim } from '@dxos/util';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Evaluate the script (with dependencies as arguments).
|
|
9
|
+
*/
|
|
10
|
+
export const evalScript = (code: string, deps: Record<string, any> = {}) => {
|
|
11
|
+
// Create a sandboxed environment that blocks access to window and document.
|
|
12
|
+
const sandbox = {
|
|
13
|
+
...deps,
|
|
14
|
+
|
|
15
|
+
// Block access to global objects.
|
|
16
|
+
console: undefined,
|
|
17
|
+
document: undefined,
|
|
18
|
+
global: undefined,
|
|
19
|
+
globalThis: undefined,
|
|
20
|
+
self: undefined,
|
|
21
|
+
window: undefined,
|
|
22
|
+
|
|
23
|
+
// Allow some safe globals.
|
|
24
|
+
Array,
|
|
25
|
+
Boolean,
|
|
26
|
+
Date,
|
|
27
|
+
Error,
|
|
28
|
+
JSON,
|
|
29
|
+
Map,
|
|
30
|
+
Math,
|
|
31
|
+
Number,
|
|
32
|
+
Object,
|
|
33
|
+
Promise,
|
|
34
|
+
RegExp,
|
|
35
|
+
Set,
|
|
36
|
+
String,
|
|
37
|
+
|
|
38
|
+
// Functions.
|
|
39
|
+
isFinite,
|
|
40
|
+
isNaN,
|
|
41
|
+
parseFloat,
|
|
42
|
+
parseInt,
|
|
43
|
+
|
|
44
|
+
// Note: undefined and null are not included as they are keywords, not variables.
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Create function with all sandbox keys as parameters.
|
|
48
|
+
const sandboxKeys = Object.keys(sandbox);
|
|
49
|
+
const sandboxValues = Object.values(sandbox);
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
52
|
+
const fn = new Function(
|
|
53
|
+
...sandboxKeys,
|
|
54
|
+
trim`
|
|
55
|
+
'use strict';
|
|
56
|
+
return ${code};
|
|
57
|
+
`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return fn(...sandboxValues);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Globals.
|
|
65
|
+
*/
|
|
66
|
+
export const builtIns = new Set([
|
|
67
|
+
// Types.
|
|
68
|
+
'Array',
|
|
69
|
+
'Date',
|
|
70
|
+
'Error',
|
|
71
|
+
'JSON',
|
|
72
|
+
'Map',
|
|
73
|
+
'Math',
|
|
74
|
+
'Number',
|
|
75
|
+
'Object',
|
|
76
|
+
'Promise',
|
|
77
|
+
'RegExp',
|
|
78
|
+
'Set',
|
|
79
|
+
'String',
|
|
80
|
+
|
|
81
|
+
// Functions.
|
|
82
|
+
'isFinite',
|
|
83
|
+
'isNaN',
|
|
84
|
+
'parseFloat',
|
|
85
|
+
'parseInt',
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Default system definitions.
|
|
90
|
+
*/
|
|
91
|
+
export const systemDefinitions = trim`
|
|
92
|
+
interface Array<T> { length: number; [n: number]: T; }
|
|
93
|
+
interface Boolean {}
|
|
94
|
+
interface Function {}
|
|
95
|
+
interface IArguments {}
|
|
96
|
+
interface Number {}
|
|
97
|
+
interface Object {}
|
|
98
|
+
interface RegExp {}
|
|
99
|
+
interface String { length: number; }
|
|
100
|
+
|
|
101
|
+
interface CallableFunction extends Function {}
|
|
102
|
+
interface NewableFunction extends Function {}
|
|
103
|
+
|
|
104
|
+
declare var console: { log(...args: any[]): void };
|
|
105
|
+
`;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { createNotebook } from '../testing';
|
|
8
|
+
|
|
9
|
+
import { ComputeGraph } from './notebook';
|
|
10
|
+
|
|
11
|
+
describe('notebook', () => {
|
|
12
|
+
test('parse dependency graph', () => {
|
|
13
|
+
const notebook = createNotebook();
|
|
14
|
+
const computer = new ComputeGraph(notebook);
|
|
15
|
+
const result = computer.parse();
|
|
16
|
+
|
|
17
|
+
const getId = (i: number) => notebook.cells[i].id;
|
|
18
|
+
|
|
19
|
+
// Check dependencies.
|
|
20
|
+
expect(result.dependencyGraph).toMatchObject({
|
|
21
|
+
[getId(0)]: [getId(1), getId(2)],
|
|
22
|
+
[getId(3)]: [getId(1)],
|
|
23
|
+
[getId(4)]: [getId(0), getId(3)],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Compute values.
|
|
27
|
+
const values = computer.evaluate();
|
|
28
|
+
expect(values).toEqual({
|
|
29
|
+
[getId(0)]: 300,
|
|
30
|
+
[getId(2)]: 200,
|
|
31
|
+
[getId(3)]: 200,
|
|
32
|
+
[getId(4)]: 500,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('evalScript blocks access to window and document', () => {
|
|
37
|
+
const notebook = createNotebook();
|
|
38
|
+
// Replace one of the cells with code that tries to access window/document.
|
|
39
|
+
if (notebook.cells[2].script?.target) {
|
|
40
|
+
notebook.cells[2].script.target.content = 'b = typeof window';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const computer = new ComputeGraph(notebook);
|
|
44
|
+
computer.parse();
|
|
45
|
+
const values = computer.evaluate();
|
|
46
|
+
|
|
47
|
+
// Should evaluate to 'undefined' since window is blocked.
|
|
48
|
+
expect(values[notebook.cells[2].id]).toBe('undefined');
|
|
49
|
+
|
|
50
|
+
// Test document access.
|
|
51
|
+
if (notebook.cells[2].script?.target) {
|
|
52
|
+
notebook.cells[2].script.target.content = 'b = typeof document';
|
|
53
|
+
}
|
|
54
|
+
computer.parse();
|
|
55
|
+
const values2 = computer.evaluate();
|
|
56
|
+
|
|
57
|
+
// Should evaluate to 'undefined' since document is blocked.
|
|
58
|
+
expect(values2[notebook.cells[2].id]).toBe('undefined');
|
|
59
|
+
|
|
60
|
+
// Test that safe globals still work.
|
|
61
|
+
if (notebook.cells[2].script?.target) {
|
|
62
|
+
notebook.cells[2].script.target.content = 'b = Math.max(100, 200)';
|
|
63
|
+
}
|
|
64
|
+
computer.parse();
|
|
65
|
+
const values3 = computer.evaluate();
|
|
66
|
+
|
|
67
|
+
// Should evaluate correctly.
|
|
68
|
+
expect(values3[notebook.cells[2].id]).toBe(200);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Signal, signal } from '@preact/signals-core';
|
|
6
|
+
|
|
7
|
+
import { log } from '@dxos/log';
|
|
8
|
+
|
|
9
|
+
import { type Notebook } from '../types';
|
|
10
|
+
|
|
11
|
+
import { evalScript } from './eval';
|
|
12
|
+
import { type ParsedExpression, VirtualTypeScriptParser } from './vfs-parser';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Compute graph that evaluates the notebook cells.
|
|
16
|
+
*/
|
|
17
|
+
export class ComputeGraph {
|
|
18
|
+
private readonly _parser = new VirtualTypeScriptParser();
|
|
19
|
+
|
|
20
|
+
private _expressions = signal<Record<string, ParsedExpression>>({});
|
|
21
|
+
private _values = signal<Record<string, any>>({});
|
|
22
|
+
|
|
23
|
+
constructor(private readonly _notebook: Notebook.Notebook) {}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parsed expressions by cell ID.
|
|
27
|
+
*/
|
|
28
|
+
get expressions(): Signal<Record<string, ParsedExpression>> {
|
|
29
|
+
return this._expressions;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Computed values by cell ID.
|
|
34
|
+
*/
|
|
35
|
+
get values(): Signal<Record<string, any>> {
|
|
36
|
+
return this._values;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Compute values.
|
|
41
|
+
*/
|
|
42
|
+
evaluate() {
|
|
43
|
+
// Parse expressions.
|
|
44
|
+
const { expressions, dependencyGraph } = this.parse();
|
|
45
|
+
this._values.value = {};
|
|
46
|
+
|
|
47
|
+
// Create a map of cell IDs to expressions for easy lookup.
|
|
48
|
+
const cellExpressions = new Map<string, ParsedExpression>();
|
|
49
|
+
Object.entries(expressions).forEach(([id, expr]) => {
|
|
50
|
+
cellExpressions.set(id, expr);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Topological sort to determine evaluation order.
|
|
54
|
+
const evaluationOrder = this.topologicalSort(Object.keys(expressions), dependencyGraph);
|
|
55
|
+
|
|
56
|
+
// Values by reference name.
|
|
57
|
+
const valuesByName: Record<string, any> = {};
|
|
58
|
+
const valuesByCellId: Record<string, any> = {};
|
|
59
|
+
|
|
60
|
+
// Evaluate cells in dependency order.
|
|
61
|
+
for (const cellId of evaluationOrder) {
|
|
62
|
+
const expr = cellExpressions.get(cellId);
|
|
63
|
+
if (!expr) {
|
|
64
|
+
log.error('no expression for cell', { cellId });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const cellSource = this._notebook.cells.find((cell) => cell.id === cellId)?.script?.target?.content;
|
|
69
|
+
if (!cellSource) {
|
|
70
|
+
log.error('no source for cell', { cellId });
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
// For assignments or declarations, evaluate and store the value.
|
|
76
|
+
if (expr.name && expr.value !== undefined) {
|
|
77
|
+
// If the parser extracted a literal value, use it directly.
|
|
78
|
+
valuesByName[expr.name] = expr.value;
|
|
79
|
+
valuesByCellId[cellId] = expr.value;
|
|
80
|
+
} else if (expr.name) {
|
|
81
|
+
// For non-literal assignments, we need to evaluate the expression.
|
|
82
|
+
// The parser identifies it's an assignment, so we can extract the RHS.
|
|
83
|
+
const equalIndex = cellSource.indexOf('=');
|
|
84
|
+
if (equalIndex !== -1) {
|
|
85
|
+
// Find the actual assignment operator (not in strings or other contexts).
|
|
86
|
+
let rhs = cellSource.substring(equalIndex + 1).trim();
|
|
87
|
+
|
|
88
|
+
// Handle semicolon at the end.
|
|
89
|
+
if (rhs.endsWith(';')) {
|
|
90
|
+
rhs = rhs.slice(0, -1).trim();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const result = evalScript(rhs, valuesByName);
|
|
94
|
+
valuesByName[expr.name] = result;
|
|
95
|
+
if (typeof result !== 'function') {
|
|
96
|
+
valuesByCellId[cellId] = result;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// For expressions without assignment, just evaluate.
|
|
101
|
+
const result = evalScript(cellSource, valuesByName);
|
|
102
|
+
valuesByCellId[cellId] = result;
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
log.error('error evaluating cell', { cellId, error });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this._values.value = valuesByCellId;
|
|
110
|
+
return valuesByCellId;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Parse expressions.
|
|
115
|
+
*/
|
|
116
|
+
parse() {
|
|
117
|
+
const expressions = this._notebook.cells
|
|
118
|
+
.filter((cell) => cell.type === 'script')
|
|
119
|
+
.reduce<Record<string, ParsedExpression>>((acc, cell) => {
|
|
120
|
+
const text = cell.script?.target?.content.trim();
|
|
121
|
+
if (text) {
|
|
122
|
+
const parsed = this._parser.parseExpression(text);
|
|
123
|
+
acc[cell.id] = parsed;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return acc;
|
|
127
|
+
}, {});
|
|
128
|
+
|
|
129
|
+
// Build dependency graph.
|
|
130
|
+
const dependencyGraph = this.buildDependencyGraph(expressions);
|
|
131
|
+
this._expressions.value = expressions;
|
|
132
|
+
return { expressions, dependencyGraph };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private topologicalSort(nodes: string[], dependencies: Record<string, string[]>): string[] {
|
|
136
|
+
const visited = new Set<string>();
|
|
137
|
+
const result: string[] = [];
|
|
138
|
+
|
|
139
|
+
const visit = (node: string) => {
|
|
140
|
+
if (visited.has(node)) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
visited.add(node);
|
|
145
|
+
|
|
146
|
+
// Visit dependencies first.
|
|
147
|
+
const deps = dependencies[node] || [];
|
|
148
|
+
deps.forEach((dep) => visit(dep));
|
|
149
|
+
result.push(node);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Visit all nodes.
|
|
153
|
+
nodes.forEach((node) => visit(node));
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private buildDependencyGraph(expressions: Record<string, ParsedExpression>): Record<string, string[]> {
|
|
158
|
+
// Create a map of variable names to their cell IDs.
|
|
159
|
+
const nameToCellId = new Map<string, string>();
|
|
160
|
+
Object.entries(expressions).forEach(([id, expr]) => {
|
|
161
|
+
if (expr.name) {
|
|
162
|
+
nameToCellId.set(expr.name, id);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Build the dependency graph using cell IDs.
|
|
167
|
+
const graph: Record<string, string[]> = {};
|
|
168
|
+
Object.entries(expressions).forEach(([id, expr]) => {
|
|
169
|
+
if (expr.references && expr.references.length > 0) {
|
|
170
|
+
// Map variable references to cell IDs.
|
|
171
|
+
const dependencyCellIds = expr.references
|
|
172
|
+
.map((ref) => nameToCellId.get(ref))
|
|
173
|
+
.filter((cellId): cellId is string => cellId !== undefined && cellId !== id);
|
|
174
|
+
|
|
175
|
+
if (dependencyCellIds.length > 0) {
|
|
176
|
+
graph[id] = dependencyCellIds;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
return graph;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { NotebookVirtualParser, VirtualTypeScriptParser } from './vfs-parser';
|
|
8
|
+
|
|
9
|
+
describe('vfs-parser', () => {
|
|
10
|
+
test('parse simple assignments', () => {
|
|
11
|
+
const parser = new VirtualTypeScriptParser();
|
|
12
|
+
|
|
13
|
+
const tests = [
|
|
14
|
+
{
|
|
15
|
+
input: 'const a = 1',
|
|
16
|
+
expected: {
|
|
17
|
+
name: 'a',
|
|
18
|
+
type: 'variable',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
input: 'a = 1',
|
|
23
|
+
expected: {
|
|
24
|
+
name: 'a',
|
|
25
|
+
type: 'variable',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
tests.forEach(({ input, expected }) => {
|
|
31
|
+
const result = parser.parseExpression(input);
|
|
32
|
+
expect(result, input).toMatchObject(expected);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('parse variable with references', () => {
|
|
37
|
+
const parser = new VirtualTypeScriptParser();
|
|
38
|
+
|
|
39
|
+
const tests = [
|
|
40
|
+
{
|
|
41
|
+
input: 'const y = x * 2',
|
|
42
|
+
expected: {
|
|
43
|
+
name: 'y',
|
|
44
|
+
type: 'variable',
|
|
45
|
+
references: ['x'],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
input: 'y = x * 2',
|
|
50
|
+
expected: {
|
|
51
|
+
name: 'y',
|
|
52
|
+
type: 'variable',
|
|
53
|
+
references: ['x'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
tests.forEach(({ input, expected }) => {
|
|
59
|
+
const result = parser.parseExpression(input);
|
|
60
|
+
expect(result, input).toMatchObject(expected);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('parse simple expression with references', () => {
|
|
65
|
+
const parser = new VirtualTypeScriptParser();
|
|
66
|
+
|
|
67
|
+
const result = parser.parseExpression('(a + b) * c');
|
|
68
|
+
expect(result).toMatchObject({
|
|
69
|
+
references: ['a', 'b', 'c'],
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('parse single expression', () => {
|
|
74
|
+
const parser = new VirtualTypeScriptParser();
|
|
75
|
+
|
|
76
|
+
const result = parser.parseExpression('const add = (a: number, b: number): number => a + b;');
|
|
77
|
+
expect(result).toMatchObject({
|
|
78
|
+
name: 'add',
|
|
79
|
+
type: 'function',
|
|
80
|
+
valueType: expect.stringContaining('(a: number, b: number) => number'),
|
|
81
|
+
returnType: 'number',
|
|
82
|
+
parameters: [
|
|
83
|
+
{ name: 'a', type: 'number' },
|
|
84
|
+
{ name: 'b', type: 'number' },
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('analyze multiple files', () => {
|
|
90
|
+
const parser = new VirtualTypeScriptParser();
|
|
91
|
+
|
|
92
|
+
const files = [
|
|
93
|
+
{
|
|
94
|
+
filename: '/test.ts',
|
|
95
|
+
content: 'export const PI = 3.14159;\nexport function square(x: number): number { return x * x; }',
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
const results = parser.analyzeFiles(files);
|
|
100
|
+
expect(results).toHaveLength(2);
|
|
101
|
+
expect(results[0]).toMatchObject({
|
|
102
|
+
name: 'PI',
|
|
103
|
+
type: 'variable',
|
|
104
|
+
valueType: '3.14159',
|
|
105
|
+
});
|
|
106
|
+
expect(results[1]).toMatchObject({
|
|
107
|
+
name: 'square',
|
|
108
|
+
type: 'function',
|
|
109
|
+
returnType: 'number',
|
|
110
|
+
parameters: [{ name: 'x', type: 'number' }],
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('notebook cell analysis', () => {
|
|
115
|
+
const parser = new NotebookVirtualParser();
|
|
116
|
+
|
|
117
|
+
const cells = [
|
|
118
|
+
{ id: 'cell1', code: 'const x: number = 10;' },
|
|
119
|
+
{ id: 'cell2', code: 'const y = x * 2;' },
|
|
120
|
+
{ id: 'cell3', code: 'console.log(y);' },
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
const analysis = parser.analyzeNotebook(cells);
|
|
124
|
+
|
|
125
|
+
// Cell 1 exports x.
|
|
126
|
+
const cell1 = analysis.get('cell1');
|
|
127
|
+
expect(cell1?.exports).toHaveLength(1);
|
|
128
|
+
expect(cell1?.exports[0]).toMatchObject({
|
|
129
|
+
name: 'x',
|
|
130
|
+
type: 'variable',
|
|
131
|
+
valueType: 'number',
|
|
132
|
+
});
|
|
133
|
+
expect(cell1?.imports).toHaveLength(0);
|
|
134
|
+
|
|
135
|
+
// Cell 2 imports x and exports y.
|
|
136
|
+
const cell2 = analysis.get('cell2');
|
|
137
|
+
expect(cell2?.exports).toHaveLength(1);
|
|
138
|
+
expect(cell2?.exports[0]).toMatchObject({
|
|
139
|
+
name: 'y',
|
|
140
|
+
type: 'variable',
|
|
141
|
+
});
|
|
142
|
+
expect(cell2?.imports).toContain('x');
|
|
143
|
+
|
|
144
|
+
// Cell 3 imports y.
|
|
145
|
+
const cell3 = analysis.get('cell3');
|
|
146
|
+
expect(cell3?.exports).toHaveLength(0);
|
|
147
|
+
expect(cell3?.imports).toContain('y');
|
|
148
|
+
});
|
|
149
|
+
});
|