New community toolkit: TypeScript-for-AutoJs6 gotchas + a fork-agnostic verification suite
First, thank you for AutoJs6 — it's the backbone of a fairly involved fleet-automation project of mine, and it's been a genuinely solid piece of software to build on.
While debugging a production bug this week, I ran into four separate, previously-undocumented (as far as I could find) mismatches between what tsc/Node-based tests accept and what AutoJs6's bundled Rhino engine actually runs — each invisible until the compiled output executed on a real device. I ended up writing a small, fork-agnostic toolkit documenting all four with runnable reproductions, in case it saves someone else the same debugging session:
https://github.com/djbclark/autojs6-typescript
Summary of what it covers (full writeup + runnable broken examples in the repo):
- Two files anywhere in the require graph independently
require()-ing the same module under the same local binding name (e.g. const log = require("./log.js") in two different files) crash the whole script the moment both load: TypeError: redeclaration of var log. (jvm-npm.js#67). Reproducible with a minimal 2-file example, independent of const/let/var, independent of which file is the entry script.
- The entry script (
main.js, executed directly by the engine, never require()'d) can't carry TypeScript's CommonJS exports stamp — any .ts file with import/export syntax gets Object.defineProperty(exports, "__esModule", ...) unconditionally, which throws ReferenceError: "exports" is not defined. when it's the entry script rather than a required module.
for...of throws EvaluatorException: syntax error at runtime specifically under "use strict" (which every tsc-compiled file has) — a parse-time error, not a compile-time one, so nothing catches it before deploy.
- Some host APIs return a Java/Kotlin object whose contract is "call
toString()" rather than a genuine JS string (confirmed case: Engine.getSource()) — calling .indexOf()/.trim()/etc. directly on it throws TypeError: Cannot find function indexOf. even when a .d.ts types it string.
I got stuck trying to reproduce #1 outside a real device — tracing RhinoJavaScriptEngine.init() / ScriptRuntime.rhinoRequireFunction suggests jvm-npm.js should ultimately delegate to Rhino's official, properly-isolating commonjs.module.Require, but I couldn't close the gap between that and what actually happens on-device (or replicate it via raw Java interop from a standalone Rhino shell) with the time I had. Full investigation notes are in the repo's examples/broken/01-redeclaration/README.md — if anyone with more Rhino/AutoJs6 internals context can pin down the exact mechanism, I'd genuinely appreciate it, and I'm happy to fold a fix or better repro back into the toolkit.
Not asking for anything here beyond a heads-up in case it's useful — feel free to close if it's not the right venue. Thanks again for the project.
New community toolkit: TypeScript-for-AutoJs6 gotchas + a fork-agnostic verification suite
First, thank you for AutoJs6 — it's the backbone of a fairly involved fleet-automation project of mine, and it's been a genuinely solid piece of software to build on.
While debugging a production bug this week, I ran into four separate, previously-undocumented (as far as I could find) mismatches between what tsc/Node-based tests accept and what AutoJs6's bundled Rhino engine actually runs — each invisible until the compiled output executed on a real device. I ended up writing a small, fork-agnostic toolkit documenting all four with runnable reproductions, in case it saves someone else the same debugging session:
https://github.com/djbclark/autojs6-typescript
Summary of what it covers (full writeup + runnable broken examples in the repo):
require()-ing the same module under the same local binding name (e.g.const log = require("./log.js")in two different files) crash the whole script the moment both load:TypeError: redeclaration of var log. (jvm-npm.js#67). Reproducible with a minimal 2-file example, independent ofconst/let/var, independent of which file is the entry script.main.js, executed directly by the engine, neverrequire()'d) can't carry TypeScript's CommonJSexportsstamp — any.tsfile withimport/exportsyntax getsObject.defineProperty(exports, "__esModule", ...)unconditionally, which throwsReferenceError: "exports" is not defined.when it's the entry script rather than a required module.for...ofthrowsEvaluatorException: syntax errorat runtime specifically under"use strict"(which every tsc-compiled file has) — a parse-time error, not a compile-time one, so nothing catches it before deploy.toString()" rather than a genuine JS string (confirmed case:Engine.getSource()) — calling.indexOf()/.trim()/etc. directly on it throwsTypeError: Cannot find function indexOf.even when a.d.tstypes itstring.I got stuck trying to reproduce #1 outside a real device — tracing
RhinoJavaScriptEngine.init()/ScriptRuntime.rhinoRequireFunctionsuggestsjvm-npm.jsshould ultimately delegate to Rhino's official, properly-isolatingcommonjs.module.Require, but I couldn't close the gap between that and what actually happens on-device (or replicate it via raw Java interop from a standalone Rhino shell) with the time I had. Full investigation notes are in the repo'sexamples/broken/01-redeclaration/README.md— if anyone with more Rhino/AutoJs6 internals context can pin down the exact mechanism, I'd genuinely appreciate it, and I'm happy to fold a fix or better repro back into the toolkit.Not asking for anything here beyond a heads-up in case it's useful — feel free to close if it's not the right venue. Thanks again for the project.