Production-grade infrastructure for Adobe ExtendScript.
|
ESON ESB64 ESARR ESSTR ESCHARS ESHTTP ESTIMER ESRAND ESUUID ESENV ESPATH ESFS ESHASH ESLOG |
ESPACK ESMIN ESABI VectorIPC ESTC ESDB COMTool ESsemble |
Also from the same team: ArcFit.dev, deterministic arc warp for Illustrator.
- Why ESTC?
- Features
- Which artifact should I use?
- Get the Release
- Installation
- Quick Start
- API
- Validation
- Performance
- Security Model
- Compatibility
- Engine quirks that shaped the design
- Development
- Repository layout
- Known limitations
- Credits
- License
Modern TypeScript tooling and Adobe ExtendScript do not share a language boundary.
Adobe's CEP TypeScript sample describes ExtendScript as an ECMAScript 3 extension, while current TypeScript no longer provides a usable ES3 output target. TypeScript deprecated target: ES3 in 5.0 and disabled it in 5.5, recommending ES5 plus a linter or another downleveling layer for remaining ES3 environments.
That creates several independent failure classes:
- modern TypeScript can accept source that an ES3-era parser rejects;
- an ES5 bundle can still contain future-reserved identifiers such as
floatorint; - generated helper code can depend on built-ins that are not portable across ExtendScript hosts;
- Adobe host typings prove compile-time shape, not parser acceptance or runtime presence;
- E4X and ExtendScript-specific syntax cannot be treated as ordinary standards ES3;
- a static parse pass is not equivalent to Illustrator's actual parser.
ESTC makes each boundary explicit and independently testable.
- Host-aware TypeScript checking — Types-for-Adobe 7.2.6 is the default declaration environment, with narrow project-owned overlays for verified current-host corrections.
- ES3 source linting — catches reserved runtime bindings, unsafe unquoted object keys, and export aliases before bundling.
- Deterministic ES5 bundling — esbuild 0.28.2 produces one IIFE boundary before compatibility normalization.
- Bundle-local helper localization — recurring generated-helper hazards are rewritten locally; ESTC does not patch persistent
Object,Function.prototype, or other Illustrator globals. - ESPACK composition — optional ESPACK build/manifest-merge stages are inserted before distribution transforms, with tool discovery, provenance reporting, safe ESB64 runtime substitution, and capability-gated shared-base64 mode.
- ESMIN final-artifact minification — optional ESMin runs only after ESPACK and ESTC assembly; ESTC then re-parses and re-audits the exact minified bytes.
- ExtendScript-safe re-emission — UglifyJS 3.19.3 re-emits quoted keys, legacy-safe property access, ASCII-only output, explicit braces, and semicolons without compression or mangling.
- Illustrator parser-output repair — AST-scoped repair handles live-proven switch/ASI parser edge cases while preserving case-expression evaluation order.
- Strict emitted-JSX gate — Acorn in
ecmaVersion: 3plus explicit ExtendScript hazard analysis rejects syntax/global leakage that a normal modern parser would permit. - Raw ExtendScript mode — E4X and Adobe/Mozilla extensions can receive compatibility scanning without a false claim of ordinary ES3 grammar conformance.
- Compile-only live parsing — optional Windows/Illustrator verification sends the complete final artifact through
DoJavaScriptinside a non-invoked function expression. - Versioned host evidence — reserved-word matrices, host-feature observations, and declaration-provenance evidence are stored separately from normative grammar rules.
- Workspace audit — report-first auditing can summarize many release/runtime artifacts without mutating the projects being inspected.
flowchart TD
Source["TypeScript source"]
Bundle["esbuild IIFE bundle (ES5)"]
Prelude["Project prelude + ESTC shims"]
Reemit["UglifyJS ExtendScript-safe<br/>compatibility re-emission"]
PreGate["Pre-distribution ESTC gate"]
ESMin["Optional ESMIN<br/>conservative minification"]
PostGate["Post-ESMIN ESTC gate"]
Live["Optional Illustrator<br/>compile-only live parse"]
Runtime["Project-specific runtime /<br/>differential tests"]
Source -->|"1. Types-for-Adobe + verified project overlays<br/>2. TypeScript AST ExtendScript source lint"| Bundle
Bundle -->|"3. Localize known generated helper dependencies<br/>4. Remove generated strict-mode prologues"| Prelude
Prelude -->|"5. Optional ESPACK build / manifest merge<br/>Inline: resolved ESB64 runtime via ESB64_RUNTIME_PATH<br/>Shared: one ESB64 runtime + --defer-b64 when supported"| Reemit
Reemit -->|"compress:false / mangle:false<br/>Reserved keys quoted, ASCII-only, explicit braces / semicolons<br/>AST-scoped Illustrator switch repair"| PreGate
PreGate -->|"6. Strict ES3 grammar + reserved-property checks<br/>7. Runtime / global-patch hazard checks"| ESMin
ESMin -->|"8. Complete assembled artifact<br/>Includes are not re-resolved here"| PostGate
PostGate -->|"9. Re-check the actual distributable bytes"| Live
Live -->|"10. Final artifact only"| Runtime
ESPACK therefore always composes before ESMIN. ESTC treats both tools as transformation boundaries rather than trust boundaries: tool output must pass the same conservative gate as ESTC's own output. A type declaration is not parser evidence; parser evidence is not runtime-behavior evidence.
The default compile-time environment is pinned to:
types-for-adobe 7.2.6
Illustrator/2022
The installed profile currently contains 412 declaration names across six source files.
Projects can layer narrow current-host corrections:
export default {
hostTypes: "Illustrator/2022",
additionalTypes: [
"./types/illustrator-2026-verified-overrides.d.ts"
]
};An override should name its evidence source: current Adobe documentation, a local scripting inventory, or a live host probe. Overlays are not a mechanism for suppressing real incompatibilities.
vendor/adobe-cep/ExtendScript.d.ts is a pinned reference copy of Adobe-CEP/Samples TypeScript/typings/ExtendScript.d.ts.
Its Git-blob identity is verified as:
40ee27eaa15abd98abbb126ae44f829f42f2b59a
audit-types currently reports seven declaration-name overlaps, two Adobe-only names, and 405 Types-for-Adobe-only names. This is provenance/parity evidence only; it is not an API- or runtime-equivalence claim.
Adobe's MIT license for that reference file is retained beside it.
| CLI | JavaScript API | |
|---|---|---|
| Entry | bin/estc.mjs |
src/index.mjs plus ./check and ./build exports |
| Interface | estc <command> |
imported functions |
| Best for | builds, CI, release gates, evidence generation | custom tooling and programmatic integration |
| Host requirement | Node.js 20+ | Node.js 20+ |
| Illustrator required | only for --live, probe-host, and probe-reserved |
only when invoking live verification |
Rule of thumb: use the CLI for project/release workflows; import the API only when ESTC is one stage inside another Node tool.
ESTC v0.2.0 adds first-class ESPACK composition and ESMIN final-artifact integration while preserving ESTC's fail-closed compatibility gates.
The release includes a deterministic source archive and checksum manifest. ESTC is not currently published to npm; source consumers should pin the Git tag rather than tracking mutable main.
Clone the repository and install the pinned dependency graph:
git clone https://github.com/thelabcorner/estc.git
cd estc
npm ciRun directly:
node bin/estc.mjs doctor
node bin/estc.mjs check path/to/script.jsx --no-targetOr expose the local CLI as estc:
npm link
estc doctorCreate extendscript.config.mjs:
export default {
host: "illustrator",
hostTypes: "Illustrator/2022",
entry: "src/index.ts",
outfile: "dist/script.jsx",
globalName: "MyScript",
target: "illustrator",
sourceLint: true,
typecheck: true,
normalize: true,
compatibilityTransforms: ["esbuild"],
compatibilityShims: [],
allowedMissingBuiltins: [],
allowedGlobalPatches: [],
prelude: [],
footer: [],
allowJson: false,
allowIncludes: false,
// Optional distribution stages:
espack: null,
esmin: null,
live: false,
liveLaunch: false
};Build:
node bin/estc.mjs build --config ./extendscript.config.mjsAdd a real Illustrator parser gate on Windows:
node bin/estc.mjs build --config ./extendscript.config.mjs --live --launchProject-specific behavioral tests remain a separate release requirement. A successful ESTC parse/build does not prove application semantics.
ESTC can own the build ordering while keeping ESPACK and ESMIN as separately installed tools:
export default {
entry: "src/index.ts",
outfile: "dist/tool.min.jsx",
globalName: "MyTool",
target: "illustrator",
espack: {
mode: "merge",
manifests: [
"../eson/dist/ESON.manifest.json",
"../esarr/dist/ESARR.manifest.json"
],
name: "my-tool",
manifestOut: "dist/my-tool.espack.json"
},
esmin: {
profile: "conservative",
keepIntermediate: true
}
};The default ESPACK lane is self-contained. ESTC resolves an ESB64 runtime from, in order, espack.esb64Runtime, ESB64_RUNTIME_PATH, an installed esb64 package, or a sibling esb64/ project. When found, that validated runtime is supplied to ESPACK through its existing ESB64_RUNTIME_PATH hook instead of accepting a stale vendored runtime.
A newer ESPACK that exposes --defer-b64 can use one shared ESB64 copy:
espack: {
mode: "merge",
manifests: ["dist/A.manifest.json", "dist/B.manifest.json"],
deferB64: true,
sharedBase64: "auto"
}doctor reports whether the resolved ESPACK supports that capability. ESTC fails closed if shared mode is requested against a tool that does not expose it.
ESPACK itself is resolved from espack.root, ESPACK_ROOT, an installed espack package, or a sibling espack/ directory. ESMIN uses the equivalent esmin.root / ESMIN_ROOT / installed-package / sibling lookup. Neither tool is copied into ESTC.
ESMIN receives the already-composed artifact and therefore runs with include expansion disabled. Relative #include ownership must be resolved before this stage; ESTC refuses esmin.skipIncludes: false rather than resolving includes relative to a temporary file. When keepIntermediate is enabled, the pre-ESMIN artifact is retained beside the final output (or at esmin.intermediateOutfile).
The final outfile is always the post-ESMIN distributable. ESTC validates once before ESMIN and again afterward, and any optional live Illustrator parse runs against the final bytes. Requested ESPACK manifest sidecars are staged privately and written to manifestOut only after those downstream gates succeed, so a rejected final build cannot leave a newly published manifest behind.
The CLI currently exposes:
estc doctor [--config FILE] [--json]
estc check FILE [--raw] [--no-target] [--allow-json] [--allow-includes] [--live] [--launch] [--json]
estc lint-ts FILE... [--json]
estc audit-types [--config FILE] [--json]
estc audit-workspace [--manifest FILE] [--live] [--launch] [--out FILE] [--json]
estc build [--config FILE] [--live] [--launch] [--json]
estc probe-host [--launch] [--out FILE] [--json]
estc probe-reserved [--launch] [--out FILE] [--json]
Reports the active Node/toolchain versions, host type profile, grammar baseline, compatibility policy, resolved configuration, and ESPACK/ESMIN discovery/capability status when those stages are enabled.
Checks an emitted JSX artifact. Conservative mode claims ES3 grammar compatibility; --raw intentionally does not and is intended for E4X/ExtendScript-only sources.
Runs the TypeScript AST source-dialect checks before bundling.
Verifies the pinned Adobe CEP declaration snapshot and inventories declaration-name overlap against the selected Types-for-Adobe profile.
Runs the complete config-driven pipeline, including optional ESPACK composition and ESMIN final-artifact minification, then writes the post-validation distributable JSX.
Aggregates diagnostics across a manifest of external artifacts. It is report-first and does not mutate the audited projects.
Runs controlled live probes and writes versioned evidence for the concrete installed Illustrator/ExtendScript engine.
Key options:
| Option | Default | Meaning |
|---|---|---|
host |
illustrator |
semantic host label |
hostTypes |
Illustrator/2022 |
Types-for-Adobe profile |
additionalTypes |
[] |
verified local .d.ts overlays |
entry |
src/index.ts |
JSX-oriented TypeScript entry |
outfile |
dist/script.jsx |
final artifact |
globalName |
unset | esbuild IIFE namespace |
target |
illustrator |
Adobe #target value |
sourceLint |
true |
TypeScript AST compatibility lint |
typecheck |
true |
host declaration type-check |
normalize |
true |
compatibility re-emission |
compatibilityTransforms |
["esbuild"] |
bundle-local generated-helper rewrites |
compatibilityShims |
[] |
built-in global shims; disabled by policy |
allowedMissingBuiltins |
[] |
explicit project capability exceptions |
allowedGlobalPatches |
[] |
intentional project-owned polyfill mutations |
prelude / footer |
[] |
raw JSX fragments/files |
allowJson |
false |
suppress JSON-global warning only when supplied/verified |
allowIncludes |
false |
whether unresolved #include is acceptable |
espack |
null |
optional ESPACK build/merge stage; accepts tool discovery, manifests/embeds, ESB64-runtime, and shared-base64 options |
esmin |
null |
optional ESMIN final-artifact stage; conservative profile by default, with optional retained pre-minify artifact |
live |
false |
compile-only Illustrator parse during build |
liveLaunch |
false |
permit the live verifier to launch Illustrator |
Paths are resolved relative to the config file.
| Check | Command | Result |
|---|---|---|
| Static test suite | npm test |
37/37 pass |
| Toolchain/environment audit | node bin/estc.mjs doctor --json |
pass on Node v22.23.2 / Windows x64 |
| Type provenance/parity | node bin/estc.mjs audit-types --json |
pinned Adobe blob verified; 412-name Types-for-Adobe profile inventoried |
| Full portable gate | npm run verify |
pass |
| ESPACK + ESMIN sibling smoke | npm run integration:siblings |
real ESON/ESARR manifests + ESPACK + ESB64 runtime + ESMIN; final ESTC gate passes |
| ESPACK + ESMIN inline live smoke | npm run integration:siblings:live |
207,875 B assembled → 201,318 B final; final minified artifact live-parses in Illustrator 30.6.0 |
| ESPACK shared-base64 live smoke | current sibling ESPACK with deferB64: "auto", sharedBase64: "auto" |
209,910 B assembled → 203,029 B final; one shared ESB64 runtime, manifest committed only after final live pass |
| ESPACK tagged compatibility | isolated v0.4.1 archive + ESMIN v1.0.0 |
207,269 B assembled → 201,048 B final; safe ESB64 runtime override active |
| ES* workspace audit | node bin/estc.mjs audit-workspace --json |
29/29 primary release/runtime artifacts pass, 0 errors |
| Live parser fixture | config-driven build with --live |
pass on Illustrator 30.6.0 / ExtendScript 4.5.6 |
| ESRAND behavioral reference | project release gate | 11/11 exact live groups on Illustrator 30.6.0 / ExtendScript 4.5.6 |
The 37 static tests cover the original grammar/runtime gates plus ESPACK/ESMIN discovery, capability gating, build ordering, shared-base64 contracts, duplicate-runtime prevention, safe ESB64 runtime substitution, transactional ESPACK sidecars, post-minification revalidation, and ESMIN include-boundary ownership.
The ES* workspace audit is ecosystem evidence, not a requirement for third-party ESTC users. Its manifest references sibling projects that are not part of this repository.
ESTC is build-time tooling; it adds no persistent runtime service.
Measured on Windows x64 with Node v22.23.2 on 2026-09-24:
| Lane | Result |
|---|---|
| 37-test static suite | 1.23 s |
| Full config-driven build fixture within the suite | 147 ms |
These figures are development-machine measurements, not cross-platform guarantees. Project compilation time scales with TypeScript graph size, bundle size, normalization work, and optional live-host startup/COM latency.
ESTC is a local build tool with an optional Adobe host boundary.
- Static
check,lint-ts,doctor, andaudit-typesdo not execute target JSX. buildexecutes the configured local Node toolchain and reads project-owned config/prelude/footer files; treat configuration files as trusted build code.- Optional ESPACK/ESMIN stages execute separately installed local tooling. ESTC does not treat their output as trusted: it validates the assembled pre-ESMIN artifact and the post-ESMIN distributable independently.
- Compile-only
--liveparsing strips Adobe preprocessor directives and sends the final emitted body to Illustrator inside a non-invoked function expression. Its purpose is parser acceptance without installing or invoking the project's globals. probe-hostandprobe-reservedintentionally execute controlled diagnostic probes in the installed host and should be treated as active evidence-generation commands.audit-workspaceis report-first and does not rewrite, clean, reset, or otherwise mutate audited sibling repositories.- Generated helper compatibility is bundle-local. ESTC does not silently patch persistent
Object,Function.prototype, or other host built-ins. - Compatibility exceptions are explicit. Missing built-ins and persistent global patches require project-owned declarations in configuration instead of hidden allowlists.
Do not run untrusted ESTC config files: like other JavaScript build configurations, they are executable Node modules.
Security reports should use GitHub's private vulnerability reporting for this repository rather than a public issue when disclosure would create avoidable risk.
| Target | Status |
|---|---|
| Node.js 20+ | supported static toolchain runtime |
| Windows x64 | supported; live Illustrator integration available |
| Linux | static toolchain supported by CI; no Illustrator live lane |
| Adobe Illustrator 30.6.0 | live parser/probe evidence recorded |
| ExtendScript 4.5.6 | live parser/probe evidence recorded |
| Illustrator type profile | Types-for-Adobe Illustrator/2022 baseline + optional verified overlays |
| ESPACK | v0.4.1 tagged merge path validated with ESTC's ESB64 runtime override; newer --defer-b64 lane capability-gated |
| ESMIN | v1.0.0 conservative final-artifact path validated |
| E4X / ExtendScript-only syntax | supported by --raw scanning; no ordinary ES3 grammar claim |
| Other Adobe hosts | static policies may be reusable, but current live evidence is Illustrator-specific |
The conservative grammar baseline is ECMA-262 3rd Edition, December 1999, §7.5 Reserved Words, parsed with Acorn ecmaVersion: 3.
ECMA-262 Edition 3 reserves a Java-era future-keyword set that modern TypeScript authoring commonly treats as ordinary property names:
abstract boolean byte char class const debugger double enum export extends
final float goto implements import int interface long native package private
protected public short static super synchronized throws transient volatile
Illustrator 30.6.0 / ExtendScript 4.5.6 rejected the complete tested reserved/future-reserved/literal set as runtime identifiers, parameters, function names, and unquoted object-literal keys.
The same parser accepted the tested tokens after dot access and bracket access. ESTC still rewrites reserved dot access to bracket access under the conservative profile rather than depending on that version-specific extension.
An ergonomic TypeScript API can be valid:
interface RNG {
float(min: number, max: number): number;
}
var value = rng.float(0, 1);while an unsafe generated representation can fail an old parser. ESTC preserves the public API while normalizing the emitted representation:
rng["float"](0, 1);and quoted object keys:
{ "float": implementation }Normal esbuild IIFE/module-export output can depend on:
Object.defineProperty;Object.getOwnPropertyDescriptor;Object.getOwnPropertyNames;Function.prototype.bind.
Illustrator 30.6.0 exposes the descriptor APIs used by esbuild's live export bindings, but ESTC does not generalize that observation to all ExtendScript engines. The helper transform is localized and fail-closed on unsupported capability or generated-helper shape drift.
Compatibility re-emission alone is insufficient for every parser shape. ESTC includes AST-scoped switch repair with tests covering nested switches, strings, regexes, comments, nested headers, terminal empty labels, and side-effectful case expressions.
E4X and Mozilla/Adobe extensions are part of real ExtendScript code. --raw exists specifically so ESTC can scan those sources for host/global hazards without pretending an ordinary ES3 parser understands their grammar.
Install and run the portable gate:
npm ci
npm run verifyUseful development commands:
npm test
npm run doctor
npm run audit:types
npm run selfcheckOptional sibling-tool integration smoke:
npm run integration:siblings
npm run integration:siblings:liveThe sibling smoke composes real ESON/ESARR ESPACK manifests, routes ESPACK through the current ESB64 runtime, runs real ESMIN, and revalidates the final artifact. It prints SKIP in a standalone clone where those sibling projects are absent.
Workspace-only ES* ecosystem audit:
npm run audit:workspace
node bin/estc.mjs audit-workspace --live --launchThe workspace manifest is intentionally relative and external to the core compiler contract. A standalone ESTC clone does not need sibling ES* repositories for its normal tests, doctor, type audit, checking, or builds.
Static CI runs without Adobe software. Live Illustrator checks are a separate evidence class and should run only on a Windows machine with an applicable Illustrator installation.
Never label a static pass as a live Illustrator runtime pass.
flowchart TD
Repo["estc/"]
Repo --> Bin["bin/"]
Bin --> CLI["estc.mjs<br/>CLI entry"]
Repo --> Data["data/"]
Data --> Profiles["host-profiles/<br/>Version-scoped host observations"]
Repo --> Evidence["evidence/<br/>Reserved-word, host, and workspace evidence"]
Repo --> Examples["examples/"]
Examples --> Config["extendscript.config.mjs<br/>Reference project configuration"]
Repo --> Projects["projects/"]
Projects --> ESRand["esrand.config.mjs<br/>Ecosystem integration fixture"]
Projects --> Audit["workspace-audit.json<br/>Optional sibling-project audit manifest"]
Repo --> Scripts["scripts/"]
Scripts --> Probe["illustrator-probe.ps1<br/>Live host probe support"]
Scripts --> Smoke["sibling-integration-smoke.mjs"]
Repo --> Src["src/"]
Src --> Build["build.mjs<br/>Config-driven compiler / distribution pipeline"]
Src --> Check["check-jsx.mjs<br/>Emitted-JSX static gate"]
Src --> Integrations["integrations/<br/>ESPACK / ESMIN discovery + process adapters"]
Src --> Modules["...<br/>Lint, normalization, live-host, provenance modules"]
Repo --> Tests["tests/"]
Tests --> Fixtures["fixtures/<br/>Portable tool / integration fixtures"]
Tests --> Static["static.test.mjs<br/>37-case static / build / integration suite"]
Repo --> Types["types/<br/>Verified local declaration overlays"]
Repo --> Vendor["vendor/"]
Vendor --> Adobe["adobe-cep/<br/>Pinned Adobe CEP declaration reference + license"]
Repo --> Package["package.json"]
Repo --> Readme["README.md"]
- The live parser/probe lane currently targets Windows COM + Adobe Illustrator; it is not a generic cross-host Adobe automation layer.
- The default compile-time Illustrator declarations are the Types-for-Adobe 2022 profile. Current-version differences require evidence-backed overlays.
- A compile-only live parse proves parser acceptance on that host/version; it does not prove project behavior.
--rawdeliberately gives up a normal ES3 grammar claim so E4X/ExtendScript-specific syntax can still be scanned.- The bundled ES* workspace audit manifest is an ecosystem integration aid, not a portable requirement for ESTC users.
- ESPACK shared-base64 mode requires a resolved ESPACK that actually exposes
--defer-b64; ESTC probes that capability and otherwise keeps the self-contained inline lane. - ESTC-owned ESMIN execution requires
skipIncludes: true; include expansion must already be complete before the final-artifact minification stage. - ESPACK, ESMIN, and ESB64 remain separately installed tools with their own release and license boundaries; ESTC does not vendor them.
- ESTC does not attempt to polyfill arbitrary missing host APIs. Project-owned compatibility behavior must remain explicit.
ESTC builds on several independently maintained projects and public references:
- ECMA International — ECMA-262 3rd Edition provides the conservative grammar and reserved-word baseline.
- Adobe CEP Samples — the pinned ExtendScript TypeScript declaration reference and its MIT license are retained in
vendor/adobe-cep/. - Types-for-Adobe — the default broad compile-time Adobe host declaration environment.
- TypeScript — authoring and type-checking frontend.
- esbuild — deterministic ES5 IIFE bundling.
- Acorn — strict ES3 grammar parsing.
- UglifyJS — ExtendScript-safe compatibility re-emission.
- docsforadobe and the ExtendScript community — maintained host/runtime documentation and accumulated engine knowledge.
Source references used by the project:
- ECMA-262 Edition 3: https://ecma-international.org/wp-content/uploads/ECMA-262_3rd_edition_december_1999.pdf
- Adobe CEP Samples: https://github.com/Adobe-CEP/Samples
- Adobe CEP TypeScript sample: https://github.com/Adobe-CEP/Samples/tree/master/TypeScript
- Types-for-Adobe: https://github.com/docsforadobe/Types-for-Adobe
- TypeScript ES3 target deprecation: microsoft/TypeScript#51909
ESTC is licensed under the MIT License.
The pinned Adobe CEP reference file under vendor/adobe-cep/ remains under Adobe's MIT license, copied alongside the file as LICENSE.adobe-cep.txt.
Optional ESPACK, ESMIN, and ESB64 integrations execute separately installed tools; those projects retain their own licenses and are not redistributed as part of ESTC.
ESTC: modern authoring in, conservative ExtendScript out, with each compatibility claim independently testable.