mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 10:17:02 -06:00
VectorCraft does not run scripts written for the reference app, and File › Scripts held only the disabled Other Script…. File › Scripts › Check Script… picks a .jsx, .jsxinc or .jsxbin file, reads it without running any of it, and shows a report: what the script needs (the script language's own objects, the document model, files, menu commands, dialogs, or features only the reference app has), what it would do outside the document, the menu-command strings it passes, the document-model member chains and type names it uses, its directives, the files it includes, and the problems that would stop it loading. Copy Report copies the report as JSON. File › Open and drag-and-drop show the report for those files too. - vectorcraft-scriptcheck, a new Standalone crate with no dependencies, holds the checker: a lexer for ECMAScript 3 with E4X literals and the #name and //@name directive lines, and an analysis of the tokens that follows variables, function scopes and the files a script includes. It never recurses: open brackets, the levels of an XML literal and the function bodies being read are kept on stacks capped at 4,096. It reads at most 8 MiB of a file and 32 MiB with the included files, follows 64 included files 16 deep, looks up at most 1,024 paths for them, keeps 1,000 entries in a list, tracks 1,000 variables holding member chains and 1,000 holding File objects, and cuts echoed text to 120 characters. A compiled script is reported as compiled and isn't read. - script.check (engine, a query) takes path, data or dataBase64. With a path and includes: true, it reads the files the #include lines name from inside the script's folder, through the automation read root, and when the script or one of those files assigns a member chain or a File object to a variable, the check treats the variable as holding it in every file. It doesn't follow absolute names, names, folders or links that lead out of the folder, names or folders longer than 4,096 bytes, or JSINCLUDE, and it reads only regular files. - ui.checkScript shows the report (dialog scriptCheck). File › Open lists Scripts (.jsx, .jsxinc, .jsxbin) and sends a script's path to script.check, which reads at most 8 MiB of it. The language rules come from ECMA-262 3rd edition and ECMA-357 2nd edition. The directive, platform and document-model root names come from the public JavaScript Tools Guide and scripting guide pages that catalog.rs cites by URL, and executeMenuCommand, doScript, loadAction, unloadAction and selectTool come from the public forum posts cited there; only names are used. Every script in the tests is written from scratch with invented names. Docs: docs/mcp.md, docs/target-app-parity.md.
180 lines
7.2 KiB
Rust
180 lines
7.2 KiB
Rust
//! The names the checker looks for, each list with the public page it comes from, and the need each
|
|
//! feature sets. Only names are taken from these pages; no description or example is copied.
|
|
|
|
use crate::Need;
|
|
|
|
// The preprocessor directives, written `#name` or `//@name`:
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/preprocessor-directives/
|
|
pub(crate) const DIRECTIVES: &[&str] = &["include", "includepath", "script", "strict", "target", "targetengine"];
|
|
|
|
// The `$` object's environment and file functions:
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/dollar-object/
|
|
pub(crate) const DOLLAR: &str = "$";
|
|
pub(crate) const DOLLAR_ENV: &[&str] = &["getenv", "setenv"];
|
|
pub(crate) const DOLLAR_EVAL_FILE: &str = "evalFile";
|
|
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/user-notification-dialogs/
|
|
pub(crate) const NOTIFY: &[&str] = &["alert", "confirm", "prompt"];
|
|
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/localizing-extendscript-strings/
|
|
pub(crate) const LOCALIZE: &str = "localize";
|
|
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/specifying-measurement-values/
|
|
pub(crate) const UNIT_VALUE: &str = "UnitValue";
|
|
|
|
// File and Folder objects, their functions and their open modes:
|
|
// https://extendscript.docsforadobe.dev/file-system-access/file-object/
|
|
// https://extendscript.docsforadobe.dev/file-system-access/folder-object/
|
|
pub(crate) const FILE: &str = "File";
|
|
pub(crate) const FOLDER: &str = "Folder";
|
|
pub(crate) const FILE_READS: &[&str] = &["read", "readch", "readln"];
|
|
pub(crate) const FOLDER_READS: &[&str] = &["getFiles"];
|
|
pub(crate) const FILE_WRITES: &[&str] = &["write", "writeln", "remove", "rename", "copy", "createAlias", "create"];
|
|
pub(crate) const FILE_DIALOGS: &[&str] = &["openDialog", "saveDialog"];
|
|
pub(crate) const FOLDER_DIALOGS: &[&str] = &["selectDialog"];
|
|
pub(crate) const INSTANCE_DIALOGS: &[&str] = &["openDlg", "saveDlg", "selectDlg"];
|
|
pub(crate) const FOLDER_PLACES: &[&str] =
|
|
&["appData", "appPackage", "commonFiles", "current", "desktop", "myDocuments", "startup", "system", "temp", "trash", "userData"];
|
|
pub(crate) const EXECUTE: &str = "execute";
|
|
pub(crate) const OPEN: &str = "open";
|
|
/// The open modes that write: write, append and edit.
|
|
pub(crate) const WRITE_MODES: &[&str] = &["w", "a", "e"];
|
|
|
|
// Windows and their types, and drawing:
|
|
// https://extendscript.docsforadobe.dev/user-interface-tools/window-object/
|
|
// https://extendscript.docsforadobe.dev/user-interface-tools/resource-specifications/
|
|
// https://extendscript.docsforadobe.dev/user-interface-tools/graphic-customization-objects/
|
|
pub(crate) const WINDOW: &str = "Window";
|
|
pub(crate) const ON_DRAW: &str = "onDraw";
|
|
pub(crate) const DRAWING: &[&str] = &["newPen", "newBrush"];
|
|
|
|
// https://extendscript.docsforadobe.dev/interapplication-communication/bridgetalk-message-object/
|
|
pub(crate) const BRIDGE_TALK: &str = "BridgeTalk";
|
|
// https://extendscript.docsforadobe.dev/external-communication/socket-object/
|
|
pub(crate) const SOCKET: &str = "Socket";
|
|
// https://extendscript.docsforadobe.dev/integrating-external-libraries/externalobject-object/
|
|
pub(crate) const EXTERNAL_OBJECT: &str = "ExternalObject";
|
|
// https://extendscript.docsforadobe.dev/scripting-xmp/xmpscript-object-reference/
|
|
pub(crate) const XMP: &[&str] = &["XMPMeta", "XMPFile", "XMPUtils", "XMPConst", "XMPDateTime"];
|
|
// https://extendscript.docsforadobe.dev/integrating-xml/the-xml-object/
|
|
pub(crate) const XML: &[&str] = &["XML", "XMLList"];
|
|
// The operators a script can define for its own classes:
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/operator-overloading/
|
|
pub(crate) const OPERATORS: &[&str] = &["+", "-", "*", "/", "%", "^", "<", "<=", "==", "<<", ">>", ">>>", "&", "|", "===", "~"];
|
|
// https://extendscript.docsforadobe.dev/extendscript-tools-features/extendscript-reflection-interface/
|
|
pub(crate) const REFLECT: &str = "reflect";
|
|
|
|
// The roots of the document model: https://ai-scripting.docsforadobe.dev/jsobjref/Application/
|
|
pub(crate) const DOM_ROOTS: [&str; 4] = ["app", "activeDocument", "documents", "selection"];
|
|
|
|
// Application methods that page doesn't list, named in public forum posts:
|
|
// https://community.adobe.com/t5/illustrator-discussions/changes-in-cs6/td-p/4173362 (executeMenuCommand,
|
|
// doScript, loadAction, unloadAction) and
|
|
// https://community.adobe.com/t5/illustrator-discussions/what-s-new-in-illustrator-scripting-cc2020/m-p/10773439
|
|
// (selectTool).
|
|
pub(crate) const MENU_COMMAND: &str = "executeMenuCommand";
|
|
pub(crate) const ACTIONS: &[&str] = &["doScript", "loadAction", "unloadAction"];
|
|
pub(crate) const SELECT_TOOL: &str = "selectTool";
|
|
/// The application methods above, which the report lists as features, not as member chains.
|
|
pub(crate) const APP_METHODS: &[&str] = &["executeMenuCommand", "doScript", "loadAction", "unloadAction", "selectTool"];
|
|
/// Text an action set written out at run time holds.
|
|
pub(crate) const ACTION_TEXT: &str = "/actionCount";
|
|
|
|
/// Constructors of the language (ECMA-262 3rd edition, section 15) and of E4X (ECMA-357 2nd edition,
|
|
/// section 13), and the platform's own: `new` of these is no document-model type.
|
|
pub(crate) const CONSTRUCTORS: &[&str] = &[
|
|
"Object",
|
|
"Function",
|
|
"Array",
|
|
"String",
|
|
"Boolean",
|
|
"Number",
|
|
"Date",
|
|
"RegExp",
|
|
"Error",
|
|
"EvalError",
|
|
"RangeError",
|
|
"ReferenceError",
|
|
"SyntaxError",
|
|
"TypeError",
|
|
"URIError",
|
|
"Namespace",
|
|
"QName",
|
|
"XML",
|
|
"XMLList",
|
|
"File",
|
|
"Folder",
|
|
"Window",
|
|
"Socket",
|
|
"BridgeTalk",
|
|
"ExternalObject",
|
|
"UnitValue",
|
|
"XMPMeta",
|
|
"XMPFile",
|
|
"XMPDateTime",
|
|
];
|
|
|
|
/// Every feature id a report can list, in the order the report lists them.
|
|
pub const FEATURES: &[&str] = &[
|
|
"actions",
|
|
"bridgeTalk",
|
|
"directive.include",
|
|
"directive.other",
|
|
"directive.target",
|
|
"directive.targetengine",
|
|
"dollar",
|
|
"dollar.env",
|
|
"dollar.evalFile",
|
|
"dynamicCode",
|
|
"e4x",
|
|
"externalObject",
|
|
"file.dialog",
|
|
"file.execute",
|
|
"file.objects",
|
|
"file.places",
|
|
"file.read",
|
|
"file.write",
|
|
"hostCheck",
|
|
"localize",
|
|
"menuCommand",
|
|
"notify",
|
|
"operatorOverloading",
|
|
"preferences",
|
|
"reflection",
|
|
"scriptui.dialog",
|
|
"scriptui.drawing",
|
|
"scriptui.palette",
|
|
"scriptui.window",
|
|
"selectTool",
|
|
"socket",
|
|
"unitValue",
|
|
"xml",
|
|
"xmp",
|
|
];
|
|
|
|
/// The need feature `id` sets.
|
|
pub(crate) fn need(id: &str) -> Option<Need> {
|
|
Some(match id {
|
|
"directive.target" | "directive.include" | "directive.other" | "dollar" | "dynamicCode" | "notify" | "localize" | "unitValue"
|
|
| "preferences" | "hostCheck" => Need::Language,
|
|
"dollar.env" | "dollar.evalFile" | "file.objects" | "file.read" | "file.write" | "file.dialog" | "file.places" | "file.execute" => {
|
|
Need::Files
|
|
}
|
|
"menuCommand" => Need::MenuCommands,
|
|
"scriptui.dialog" | "scriptui.window" | "scriptui.drawing" => Need::Dialogs,
|
|
"directive.targetengine"
|
|
| "scriptui.palette"
|
|
| "bridgeTalk"
|
|
| "socket"
|
|
| "externalObject"
|
|
| "xmp"
|
|
| "xml"
|
|
| "e4x"
|
|
| "operatorOverloading"
|
|
| "reflection"
|
|
| "actions"
|
|
| "selectTool" => Need::HostOnly,
|
|
_ => return None,
|
|
})
|
|
}
|