Skip to content

EVAL JavaScript

Evaluates a short piece of JavaScript and stores the result in one stash variable. The palette lists it as SET JS EXPR, next to the other variable ops, because that is what it is: an assignment whose right-hand side happens to be JavaScript.

Use it when a value needs a line or two of JavaScript to compute and you want the target variable visible in the tree. When the block grows past that, move it to Server CODE, which takes the same JavaScript, adds Perl as an option and gives you a real editor to work in. For the Perl equivalent of this op, see SET EXPR.

Fields

Variable

The stash variable that receives the result. Write the name on its own, with no ${} around it. The field starts out holding myvar.

Clear the field and the op falls back to the node's name, lowercased, with spaces and punctuation replaced by _. An op named Next build number then writes to next_build_number, and an op you never renamed writes to set_js_expr. Rename the op afterwards and the variable name moves with it, which breaks every later op that read the old name.

An existing variable of that name is overwritten. There is no append; use PUSH VAR for that.

ClaJS Expression

The JavaScript, in a syntax-highlighted editor. The value stored is whatever the last expression evaluates to.

The field is not empty when you open it. It arrives holding a worked sample:

// enter js code here
// variables in the stash are available as cla.stash("myvar")
// the last line will be returned into the receiving variable

parseInt(cla.stash("myvar")) + 1;

That text is the field's value, not a placeholder. Apply the form, save the rule, and the sample is what runs: it reads myvar from the stash, adds one and writes the result back. With no myvar in the stash the result is NaN, stored without complaint.

Reach the stash through cla.stash, described in cla/stash. cla.stash('foo') reads, cla.stash('foo', 3) writes straight into the rule's stash, and cla.stash() returns the whole stash. Nested values take a slash path, cla.stash('/topic/title'); a dotted name such as cla.stash('topic.title') returns nothing. The modules listed in the Clarive JavaScript DSL are available through require.

Two habits from other JavaScript environments do not carry over here.

A declaration is not an expression, and the fallback in this case is not an empty value. Ending the field with var total = a + b; stores the string use strict, because that is the last value the engine produced. End with total; on a line of its own.

A top-level return is a syntax error, because the code is not wrapped in a function. The op fails with a JavaScript error rather than returning anything.

${...} placeholders are not expanded in this field. Read stash values through cla.stash instead.

What lands in the variable

Strings and numbers arrive as you would expect. An array or an object arrives as a real structure rather than as text, so a list computed here can be tested with HAS and IN in IF var condition THEN and extended later with PUSH VAR.

Each run gets a brand new JavaScript engine. Nothing carries over from a previous EVAL JavaScript op or from a Server CODE block, and every require reloads. Inside a loop that startup cost is paid on every iteration.

An error in the expression stops the rule. The message names JavaScript as the source and carries a line number counted from the first line you typed in the field. Trap it with Error Handling on the op's Options tab, or by wrapping the op in TRY statement and CATCH statement.

The op writes one entry to the job log, its name, and nothing about the value it computed. To see the result, log it with LOG Message or from inside the expression.

Return Key on the Options tab has no role here. The Variable field is what decides where the value lands.

Combining with other ops

The natural pairing is a condition op reading the variable straight after: IF var condition THEN with the Numeric option ticked when the value came out of arithmetic, because text ordering puts 9 after 10.

Inside WHILE condition, this op is the usual way to move the loop counter. A loop whose body never updates the variable it tests never ends.

For a value that does not need JavaScript at all, SET VAR takes a literal or a ${...} template and reads better in the tree.

Examples

Advance a counter that a loop tests. The || 0 matters on the first pass, when the variable does not exist yet.

Variable: attempt
ClaJS Expression:

  (parseInt(cla.stash('attempt')) || 0) + 1;

Pick one value out of a structure another op put in the stash, with a fallback.

Variable: owner_email
ClaJS Expression:

  var topic = cla.stash('topic') || {};
  var owners = topic.owners || [];

  owners.length ? owners[0].email : 'release-team';

Normalise a name before it is used to build a path.

Variable: safe_project
ClaJS Expression:

  String(cla.stash('project') || '')
      .toLowerCase()
      .replace(/[^a-z0-9]+/g, '-');