aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/Scripting.ts
diff options
context:
space:
mode:
authorNaafiyan Ahmed <naafiyan@gmail.com>2022-08-10 17:12:58 -0400
committerNaafiyan Ahmed <naafiyan@gmail.com>2022-08-10 17:12:58 -0400
commit9dae453967183b294bf4f7444b948023a1d52d39 (patch)
tree986f4a79b8c5b92013a70b5ecba704bbba4a7ff8 /src/client/util/Scripting.ts
parentc80d0763c87d1965f451bbd7b31d8da8228dc048 (diff)
parent513dcaa2d8c86f1cb5236ce89062cace6f418d1b (diff)
Merge branch 'master' into data-visualization-view-naafi
Diffstat (limited to 'src/client/util/Scripting.ts')
-rw-r--r--src/client/util/Scripting.ts65
1 files changed, 33 insertions, 32 deletions
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 3791bec73..ea2bf6551 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -5,12 +5,11 @@
// import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
// @ts-ignore
import * as typescriptlib from '!!raw-loader!./type_decls.d';
-import * as ts from "typescript";
-import { Doc, Field } from "../../fields/Doc";
-import { scriptingGlobals, ScriptingGlobals } from "./ScriptingGlobals";
+import * as ts from 'typescript';
+import { Doc, Field } from '../../fields/Doc';
+import { scriptingGlobals, ScriptingGlobals } from './ScriptingGlobals';
export { ts };
-
export interface ScriptSuccess {
success: true;
result: any;
@@ -46,7 +45,6 @@ export function isCompileError(toBeDetermined: CompileResult): toBeDetermined is
return false;
}
-
function Run(script: string | undefined, customParams: string[], diagnostics: any[], originalScript: string, options: ScriptOptions): CompileResult {
const errors = diagnostics.filter(diag => diag.category === ts.DiagnosticCategory.Error);
if ((options.typecheck !== false && errors.length) || !script) {
@@ -63,7 +61,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
const run = (args: { [name: string]: any } = {}, onError?: (e: any) => void, errorVal?: any): ScriptResult => {
const argsArray: any[] = [];
for (const name of customParams) {
- if (name === "this") {
+ if (name === 'this') {
continue;
}
if (name in args) {
@@ -86,11 +84,10 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
return { success: true, result };
} catch (error) {
-
if (batch) {
batch.end();
}
- onError?.(script + " " + error);
+ onError?.(script + ' ' + error);
return { success: false, error, result: errorVal };
}
};
@@ -151,16 +148,16 @@ class ScriptingCompilerHost {
}
export type Traverser = (node: ts.Node, indentation: string) => boolean | void;
-export type TraverserParam = Traverser | { onEnter: Traverser, onLeave: Traverser };
+export type TraverserParam = Traverser | { onEnter: Traverser; onLeave: Traverser };
export type Transformer = {
- transformer: ts.TransformerFactory<ts.SourceFile>,
- getVars?: () => { capturedVariables: { [name: string]: Field } }
+ transformer: ts.TransformerFactory<ts.SourceFile>;
+ getVars?: () => { capturedVariables: { [name: string]: Field } };
};
export interface ScriptOptions {
requiredType?: string; // does function required a typed return value
- addReturn?: boolean; // does the compiler automatically add a return statement
+ addReturn?: boolean; // does the compiler automatically add a return statement
params?: { [name: string]: string }; // list of function parameters and their types
- capturedVariables?: { [name: string]: Field }; // list of captured variables
+ capturedVariables?: { [name: string]: Doc | number | string | boolean }; // list of captured variables
typecheck?: boolean; // should the compiler perform typechecking
editable?: boolean; // can the script edit Docs
traverser?: TraverserParam;
@@ -169,24 +166,28 @@ export interface ScriptOptions {
}
// function forEachNode(node:ts.Node, fn:(node:any) => void);
-function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, indentation = "") {
- return onEnter(node, indentation) || ts.forEachChild(node, (n: any) => {
- forEachNode(n, onEnter, onExit, indentation + " ");
- }) || (onExit && onExit(node, indentation));
+function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, indentation = '') {
+ return (
+ onEnter(node, indentation) ||
+ ts.forEachChild(node, (n: any) => {
+ forEachNode(n, onEnter, onExit, indentation + ' ');
+ }) ||
+ (onExit && onExit(node, indentation))
+ );
}
export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult {
- const { requiredType = "", addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options;
+ const { requiredType = '', addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options;
if (options.params && !options.params.this) options.params.this = Doc.name;
if (options.params && !options.params.self) options.params.self = Doc.name;
if (options.globals) {
ScriptingGlobals.setScriptingGlobals(options.globals);
}
- const host = new ScriptingCompilerHost;
+ const host = new ScriptingCompilerHost();
if (options.traverser) {
const sourceFile = ts.createSourceFile('script.ts', script, ts.ScriptTarget.ES2015, true);
- const onEnter = typeof options.traverser === "object" ? options.traverser.onEnter : options.traverser;
- const onLeave = typeof options.traverser === "object" ? options.traverser.onLeave : undefined;
+ const onEnter = typeof options.traverser === 'object' ? options.traverser.onEnter : options.traverser;
+ const onLeave = typeof options.traverser === 'object' ? options.traverser.onLeave : undefined;
forEachNode(sourceFile, onEnter, onLeave);
}
if (options.transformer) {
@@ -199,17 +200,17 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
}
const transformed = result.transformed;
const printer = ts.createPrinter({
- newLine: ts.NewLineKind.LineFeed
+ newLine: ts.NewLineKind.LineFeed,
});
script = printer.printFile(transformed[0]);
result.dispose();
}
const paramNames: string[] = [];
- if ("this" in params || "this" in capturedVariables) {
- paramNames.push("this");
+ if ('this' in params || 'this' in capturedVariables) {
+ paramNames.push('this');
}
for (const key in params) {
- if (key === "this") continue;
+ if (key === 'this') continue;
paramNames.push(key);
}
const paramList = paramNames.map(key => {
@@ -217,21 +218,21 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
return `${key}: ${val}`;
});
for (const key in capturedVariables) {
- if (key === "this") continue;
+ if (key === 'this') continue;
const val = capturedVariables[key];
paramNames.push(key);
- paramList.push(`${key}: ${typeof val === "object" ? Object.getPrototypeOf(val).constructor.name : typeof val}`);
+ paramList.push(`${key}: ${typeof val === 'object' ? Object.getPrototypeOf(val).constructor.name : typeof val}`);
}
- const paramString = paramList.join(", ");
- const body = addReturn && !script.startsWith("{ return") ? `return ${script};` : script;
+ const paramString = paramList.join(', ');
+ const body = addReturn && !script.startsWith('{ return') ? `return ${script};` : script;
const reqTypes = requiredType ? `: ${requiredType}` : '';
const funcScript = `(function(${paramString})${reqTypes} { ${body} })`;
- host.writeFile("file.ts", funcScript);
+ host.writeFile('file.ts', funcScript);
if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
- const program = ts.createProgram(["file.ts"], {}, host);
+ const program = ts.createProgram(['file.ts'], {}, host);
const testResult = program.emit();
- const outputText = host.readFile("file.js");
+ const outputText = host.readFile('file.js');
const diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics);