skip to content

In ZAP, what happens to a saved script whose recorded engine name is Nashorn?

level: middleimportance: nice to knowfreq 20%

answer

  1. the name is rewritten, not rejected
  2. the engine left the Java runtime
  3. a substring test, not an exact match
  4. no engine means the script cannot be enabled
  5. every language ships as its own add-on

basics

~20 s

The engine lookup silently rewrites any name containing Nashorn to Graal.js, because that engine left the supported Java runtimes. If the add-on providing the replacement is absent there is no engine, and the script cannot be enabled.

solid answer

~40 s

The script extension rewrites the lookup: any recorded engine name containing `Nashorn` is replaced with `Graal.js` before the wrapper is resolved. That keeps older saved scripts pointing at a JavaScript engine that still exists, since the one they were written against left the Java runtime. The replacement is a separate add-on, and it is not at release status — so "write a hook in JavaScript" depends on installing something that is still marked alpha. If no engine resolves, the consequence is quiet: enabling a script with no engine is refused outright, so the hook simply never fires. Every scripting language the tool offers arrives this way, as an add-on, and none of them is at release status.

go deeper

for a junior

Remember that the old JavaScript engine is gone from the Java runtime and the tool substitutes the current one by name. You do not have to edit old scripts for that reason alone.

for a middle

Explain that the substitution is a substring test done at engine lookup and that it is silent, and say where the replacement engine comes from — a separate add-on rather than the core program.

for a senior

Show that you would treat the engine as a build dependency. Its absence is not an error: the script cannot be enabled, the hook never fires, and the run finishes looking clean.

for a principal

The tradeoff to own is depending on a scripting seam whose language layer has never been promoted past alpha or beta. Decide whether pipelines may rely on it, and what has to be pinned and asserted if they do.

## The rewrite itself Each saved script records the engine it was written for. When the script extension resolves that name to an engine wrapper, it first checks whether the name **contains** `Nashorn`, and if so substitutes `Graal.js`. The reason is in the code's own comment: that engine is no longer included in any of the Java runtimes the project supports. The substring test is deliberate, because the recorded names are compound — a language name and an engine name joined together — so an exact match would miss most of them. The rewrite is **silent**. Nothing warns you that the script you are running is not running on the engine it was written for, which matters because the two are not identical in behaviour for anything beyond simple code. ## Why this is the leaf's real catch The hook contracts are stable: fixed function names, fixed arguments, a fixed moment when each fires. The language you write them in is not. Every scripting engine is a separate add-on, and **not one of them is at release status** — the JavaScript one is marked alpha, and none of the others has been promoted past beta. So the contract is core-shaped and the implementation is an add-on nobody has promoted. That produces a stack that surprises people assembling an unattended build: | layer | where it comes from | |---|---| | the script's entry points | an interface core still declares, marked deprecated for removal | | the `httpsender`, `proxy` and `targeted` types and the listeners that fire them | the `scripts` add-on | | the language the script is written in | a further add-on per language, none at release status | A build that omits any one of those three layers has no working hook, and the failure is a missing capability rather than an error. ## What happens when no engine resolves This is the part worth rehearsing, because it is quiet at every step: 1. The lookup rewrites the name, then searches the registered wrappers and the runtime's own engine factories. 2. If nothing matches, no engine is attached to the script. 3. Enabling a script that has no engine is **refused** — the request returns without doing anything. 4. The hook therefore never fires, and no message is affected. Nothing here raises an alert, fails a run, or appears in a report. From the outside it is indistinguishable from a hook that ran and chose to do nothing, which is the same diagnostic problem a script that disabled itself creates. ## The command-line path has the same shape Running a script from the command line resolves its engine from the **file extension**, not from anything inside the file. If no engine claims that extension, the program prints an informational line and moves on. The same is true if the file does not exist, cannot be read, or has no extension at all. Four different mistakes, four informational messages, and a run that continues as though nothing was asked of it. Two further properties of that path are easy to get wrong. The script is always loaded as a **standalone** script whatever its content, so a file containing sender-hook functions does not become a sender hook this way. And it is only invoked automatically when there is no desktop — with a desktop present the file is loaded for you to run yourself. ## Why this matters more in a pipeline than on a desktop On a desktop the absence of an engine is visible: the script sits there and will not turn on. Unattended, the same state produces a run that looks identical to a healthy one. The three ways that happens are worth separating: - The engine add-on was never in the build, so the type resolves but the language does not. - The engine add-on is present but the script names an engine nothing claims, and no substitution rule covers that name. - The script has an engine and is simply not enabled, which looks the same from outside again. ## What to do about it - Treat the language engine as a build dependency and assert it is present, rather than discovering its absence as silence. - Do not assume a script written years ago still runs on the engine it names; the substitution is automatic and unannounced. - Prefer checking that a hook produced its own evidence over checking that the run finished, because every failure mode in this chain ends in a run that finishes normally.

  • Why is the check a substring test rather than a comparison against a fixed engine name?
    Because the recorded value is a compound label built from the language name and the engine name, so the stored strings vary. Testing whether the name contains the old engine's name catches every saved variant; an exact comparison would miss most of them.
  • What does the command-line script option do if no engine claims the file's extension?
    It prints an informational line and carries on. The same happens for a missing file, an unreadable file, or a file with no extension — none of them is an error, and none of them changes what the run returns.
  • If the language engine add-on is missing, how does the failure present itself?
    As silence. No engine attaches to the script, enabling it is refused, and the hook never fires. There is no alert, no report entry and no change to the run's status, so it looks exactly like a hook that ran and did nothing.

It is like a document that names a font the machine no longer has. The renderer quietly substitutes another and prints anyway; it is only when the spacing looks wrong that anyone notices a substitution happened at all.

saying these in an interview costs you the question

  • Thinks the old engine still ships inside the Java runtime
  • Expects a warning when the engine name is substituted
  • Believes the JavaScript engine is part of the core program
  • Assumes a missing engine raises an error at load time
  • Says the command-line option runs a script as whatever type it contains