Merge pull request #6804 from dotCooCoo/fix/script-checker-name-escapes

Script checker: names with escaped characters are read as names
This commit is contained in:
BFlat
2026-11-12 15:13:04 +07:00
committed by GitHub
8 changed files with 356 additions and 62 deletions
+7 -4
View File
@@ -1648,9 +1648,9 @@ control character, in the first 8 KiB) or `tooLarge` (over 8 MiB). For a script,
`menuCommand` or `e4x`), each with a count and its lines.
- `dom.members` lists the document-model member chains as the script writes them
(`app.activeDocument.layers[].name`, with `[]` for an index and `()` for a call); a variable assigned from a chain
is replaced by that chain, and a name written with `\u` escapes is read as the name it spells. `dom.types` lists
the type names the script compares with `.typename` or creates with `new`, apart from the language's, the platform's
and the script's own functions.
is replaced by that chain, and a name written with `\uXXXX` or `\u{…}` escapes is read as the name it spells.
`dom.types` lists the type names the script compares with `.typename` or creates with `new`, apart from the
language's, the platform's and the script's own functions.
- `menuCommands.strings` lists the string literals the script passes to `executeMenuCommand`
(`app.executeMenuCommand('…')`), each with a count and its lines, and `menuCommands.dynamic` counts the calls
whose argument isn't a string literal.
@@ -1662,7 +1662,10 @@ control character, in the first 8 KiB) or `tooLarge` (over 8 MiB). For a script,
template literals and XML literals that aren't closed, brackets that don't match, syntax newer than ES3 and
unknown directives) and notes on its text (bytes that aren't valid UTF-8, mixed line endings, and nesting deeper
than the check follows: more than 4,096 open brackets, or XML literals and the code in their braces nested more
than 4,096 levels deep).
than 4,096 levels deep). Newer syntax includes a private name (`#name`, given with its escapes read, unless the
name they spell would make the line a directive) and a `\u{…}` escape in a name (given as written). A `#` and a
name at the start of a line is a private name, not a directive, when the name starts with an escape, or when the
line is inside braces and the name is not a directive's.
Each entry of `targets`, `directives`, `includes` and `problems` has the `line` it is on (a problem with the whole
text has none) and, when it is in an included file, that file's path as `file`. `features`, `menuCommands.strings`
+1 -1
View File
@@ -769,7 +769,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- MCP protocol: five prompts (`prompts/list` / `prompts/get`: poster, icon set, recolour, trace-and-style, export set), `completion/complete` for prompt arguments and template variables read from the live catalogues (formats, effect ids, command ids, trace presets, swatch and object ids), four resource templates (`vectorcraft://object/{id}`, `//command/{id}`, `//effect/{id}`, `//swatch/{name}`) so an agent reads one thing instead of the whole document, and `logging/setLevel` with `notifications/message`. `window.panel` ids are case-insensitive (display labels work too), `vectorcraft://object/{id}` reads through `document.node {summary: true}` (the same reply bytes from one lookup instead of summarizing the whole document: a leaf read on a 2,000-object document drops from ~20 ms to ~0.06 ms), large containers slice with `document.node {depth?, childLimit?}` (truncated levels report `childCount`), `document.inspect` and the `inspect_document` tool slice the same way so a depth-0 read is the layer skeleton (~9.7 KB instead of ~2 MB on a 2,000-object document), `document.find` locates nodes by name/kind/text with ancestor paths, and the CLI sweeps the protocol surface over stdio against the compiled binary. `docs/mcp.md` has a Protocol section covering the capability table and what is deliberately absent (subscriptions, progress, cancellation, sampling, elicitation, Streamable HTTP — all of which need the transport to interleave reads).
- Headless CLI (`vectorcraft-cli run`, `convert`, `info`, `bench`, `perf`, `mcp`). A `run` step, like a `command_batch` step over MCP, can use an earlier step's result (`"$1.id"`, #785); `run --commands FILE` (or `-` for standard input) reads the steps from a JSON array or JSON Lines, past the Windows command-line limit (#3147, `apps/vectorcraft-cli/tests/it/cli.rs` `run_reads_*`, `run_refuses_malformed_commands_naming_the_step`).
- File › Scripts › Check Script… reads a script written for Illustrator (`.jsx`, `.jsxinc` or a compiled `.jsxbin`) without running any of it and reports what it needs (the document model, files, dialogs, menu commands, features only Illustrator has), what it would do outside the document, the menu commands and document-model members it uses, its directives and included files, and the problems that would stop it loading (`script.check`, which also reads `.js` files); File › Open and drag-and-drop show the report for `.jsx`, `.jsxinc` and `.jsxbin` files.
- Check Script reads names by the same identifier rule as `vectorcraft-js`: Unicode 17.0 `ID_Start` characters, `$` and `_` start a name, and `ID_Continue` characters and `$` continue it (https://www.unicode.org/reports/tr31/, https://tc39.es/ecma262/#sec-names-and-keywords). U+2118, U+203F, U+00B7 and the zero width non-joiner and joiner are name characters, and U+00B2 and U+2E2F are not. Of the characters Unicode 17.0 assigned, U+088F starts a name and U+1ACF may follow its first character. A `\uXXXX` escape is read as its character only where a name may hold it, so `\u0030abc` does not become a name that starts with a digit. Tests: `crates/scriptcheck/src/tests.rs` (`names_are_made_of_the_unicode_identifier_characters`, `an_escape_stands_for_a_character_only_where_a_name_may_hold_it`), `crates/engine/tests/it/js_lexer_vs_scriptcheck.rs` (`both_lexers_take_the_same_characters_into_names`).
- Check Script reads names by the same identifier rule as `vectorcraft-js`: Unicode 17.0 `ID_Start` characters, `$` and `_` start a name, and `ID_Continue` characters and `$` continue it (https://www.unicode.org/reports/tr31/, https://tc39.es/ecma262/#sec-names-and-keywords). U+2118, U+203F, U+00B7 and the zero width non-joiner and joiner are name characters, and U+00B2 and U+2E2F are not. Of the characters Unicode 17.0 assigned, U+088F starts a name and U+1ACF may follow its first character. A `\uXXXX` escape is read as its character only where a name may hold it, so `\u0030abc` does not become a name that starts with a digit; a `\u{…}` escape takes any number of hexadecimal digits up to U+10FFFF, and one that is empty, unclosed, out of range or a surrogate is not part of a name. Each `\u{…}` escape read in a name is reported as syntax newer than ES3, which has only the four-digit form (https://ecma-international.org/wp-content/uploads/ECMA-262_3rd_edition_december_1999.pdf, section 7.6). A private name may start with an escape (`this.#\u{61}pp` is the private name `#app`), and a private name at the start of a line inside braces is not read as a directive unless its name is a directive's. Tests: `crates/scriptcheck/src/tests.rs` (`names_are_made_of_the_unicode_identifier_characters`, `an_escape_stands_for_a_character_only_where_a_name_may_hold_it`, `braced_escapes_in_names_are_read_by_their_value`, `braced_name_escape_reports_later_syntax_and_member`, `private_names_with_escaped_starts_are_single_tokens`, `private_name_at_line_start_is_not_a_directive`), `crates/engine/tests/it/js_lexer_vs_scriptcheck.rs` (`both_lexers_take_the_same_characters_into_names`).
- `vectorcraft-js` parses JavaScript as ECMAScript 5.1 defines it, with the legacy octal forms, block functions and lenient regular expressions of Annex B, into a syntax tree with source spans; it reads the `#target`, `#include` and other preprocessor lines as directives without running them, and a script that breaks the grammar or an early-error rule gives a `SyntaxError` with its line and column. Nesting past the parser's depth limit (`Options::max_depth`, 200 by default) gives a `SyntaxError` instead of exhausting the stack. `cargo xtask test262` fetches the conformance suite at a pinned commit and parses its ES5 tests: 5,411 of 5,418 runs pass (the 7 others use `let` and `const`). This entry covers parsing; the next entry covers running scripts. Tests: `crates/js/src/tests.rs`, `crates/engine/tests/it/js_lexer_vs_scriptcheck.rs`.
- `vectorcraft-js` identifiers, written out or as `\uXXXX` and `\u{...}` escapes, take the characters Unicode's `ID_Start` and `ID_Continue` properties allow (https://www.unicode.org/reports/tr31/), plus `$` and, at the start, `_`, as later ECMAScript editions define them (https://tc39.es/ecma262/#sec-names-and-keywords). `Other_ID_Start` characters such as U+2118 and `Other_ID_Continue` characters such as U+00B7 and the zero width non-joiner and joiner are accepted, and no `Pattern_Syntax` or `Pattern_White_Space` character is. Letter categories come from Unicode 17.0, so U+088F starts an identifier and U+1ACF may follow its first character; characters assigned after Unicode 17.0 are not yet identifier characters. Tests: `crates/js/src/tests.rs` (`identifier_characters_are_unicode_17_id_start_and_id_continue`, which checks every code point, `identifiers_take_the_characters_unicode_17_assigned`, `identifiers_take_the_other_id_start_and_continue_characters`, `identifiers_refuse_pattern_syntax_surrogates_and_bad_escapes`, `no_pattern_syntax_or_white_space_character_is_an_identifier_character`).
- `vectorcraft-js`'s `Realm` runs ECMAScript 5.1 scripts: the parsed script compiles to verified bytecode that a non-recursive interpreter runs, with closures, `this`, `arguments`, `with`, direct and indirect `eval`, `new Function`, `try`/`catch`/`finally`, labeled `break` and `continue`, and `for`-`in` in insertion order, over a mark-and-sweep heap, with the built-ins the next two entries list. Every run is bounded by fuel, heap bytes, frames, nested host calls and an interrupt flag (smaller defaults in the wasm build), and a run that reaches a limit stops with a limit error that `try` cannot catch. `cargo xtask test262` also runs the suite's ES5 language tests that need only the built-ins present: 4,280 of 4,286 runs pass (4 of the others expect the completion values of later editions, and 2 expect a configurable function `length`). The app does not call it yet. Tests: `crates/js/src/interp_tests.rs`, `crates/js/tests/test262.rs`.