Changes to Javascript step behavior

Executing “untrusted” code is tricky. Bad actors can write malicious code and potentially access sensitive data.

The current way the javascript step is set up is a security risk and we want to move off of it at the earliest opportunity. Luckily there is a new backend that is both secure and more performant:
It's now 70-94% faster, there will be more information about that in another post.

All Javascript steps created after July 30th, 2024 already automatically use the new system. We’ll be slowly converting existing Javascript step to use the new system, with the cutoff by August 16, 2024.

The goal of the javascript step is to provide quick scripting to manipulate variables, rather than be a heavy-load serverless function with networking. For that, we can use functions.

No action is needed is on your end, unless you use the following patterns.

We've monitored all javascript step errors for the past week, running both the new and old backends in parallel, to categorize impact and effects.
For the select few users that are affected, we will be proactively reaching out to them.

All breaking changes we've observed will all be documented here, so people don't reimplement in the future.

Major breaking changes

requireFromUrl

The javascript step used to support requireFromUrl() which allows users to load in 3rd party libraries via URL. Commonly libraries such as moment or lodash and other utilities. This method is actually an anti pattern and has major security risks that the new backend does not support.

// example usage of requireFromUrl
const moment = requireFromUrl("https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js");

time = moment().add(1, 'hours');

This will no longer work after the cutoff, the Javascript step will go down the fail port with a debug message saying: ReferenceError: fetch is not defined"

nodeJS modules: buffer

Our new backend does not run on NodeJS, but rather a v8 isolate.

Calls specific to NodeJS modules rather than the Javascript/ECMAScript standard will no longer be supported.

// example of using nodeJS modules
let buff = new Buffer(token, 'base64');
name = buff.toString('ascii');

This will no longer work after the cutoff, the Javascript step will go down the fail port with a debug message saying "ReferenceError: [module] is not defined".

There are low level alternatives to replicate the behavior of nodeJS utilities, and this is something LLMs excel at helping convert (be sure to test, of course!).

If you are using Buffer for base64 encoding/decoding, you can easily polyfill a atob or btoa function:

function atob(e){let r="";if((e=e.replace(/=+$/,"")).length%4==1)throw Error("Invalid base64 string");for(let t=0,n,a,o=0;a=e.charAt(o++);~a&&(n=t%4?64*n+a:a,t++%4)&&(r+=String.fromCharCode(255&n>>(-2*t&6))))a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a);return r}
function btoa(t){let a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",h="",r=0;for(;r<t.length;){let e=t.charCodeAt(r++),$=r<t.length?t.charCodeAt(r++):Number.NaN,c=r<t.length?t.charCodeAt(r++):Number.NaN;h+=a.charAt(e>>2&63),h+=a.charAt((e<<4|$>>4&15)&63),h+=isNaN($)?"=":a.charAt(($<<2|c>>6&3)&63),h+=isNaN(c)?"=":a.charAt(63&c)}return h}

// converts base64 to ascii, equivalent of Buffer.from(base64ref, 'base64')
atob(base64ref)

// converts ascii to base64
btoa("hello world")

JSON.stringify(this)

The this keyword now has a circular reference, and calling JSON.stringify(this) will result in recursion:

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'global'
--- property 'global' closes the circle"

You can still use this.

Other minor changes

DateTimeFormat

Intl.DateTimeFormat() constructor. As per the MDN documentation:

If any of the date-time component options is specified, then dateStyle and timeStyle must be undefined.

so Date(A).toLocaleTimeString.(B, { timeZone, timeZoneName, timeStyle }) would crash.

fetch

The fetch() command already doesn't work today - we don't really support any await or async actions, but after the cutoff, the Javascript step will go down the fail port, with a debug message saying "ReferenceError: fetch is not defined".

resource changes

The new backend solution has the same timeout but will have a definited limit on CPU and memory.
In our monitoring no present blocks are affected by these limits.