JavaScript UDFs
This guide covers general JavaScript UDF (user-defined function) requirements, usage details, as well as limitations and supported language features.
Intoductory Example
The following example shows how to write a custom JavaScript UDF to execute an Automation when a state condition is met. This example takes advantage of some
built-in functionality, such as the executeAutomation()
and getState()
functions.
var state = getState('office-temp');
// Execute an automation when the temperature
// is greater than 20 degrees
if (parseInt(state.value) > 20) {
executeAutomation('0181feaf-0d01-4e4f-942e-e3bbccdeee94');
}
Built-in Functions
The default JavaScript UDF environment has a number of built-in functions, however we've extended the built-in functions to include a range of functionality to interface and program different features within the Twin Engine. This can be anything from triggering an Automation to creating a new Model.
- State - View how to manage unstructured global state
- Models - View how to manage the modelling of your domain
- Alarms (Legacy) - View how to manage Alarms (Legacy) for when something requires attention
- Events - View how to manage and query Events that have been raised
- Blobs - View how to manage blobs of data
- Automations - View how to interact and execute Automations
- Miscellaneous - View available miscellaneous functionality
Limits & Restrictions
Below is a table of all the limitations which are applied to each UDF execution. Violation of this limits will result in either the UDF not executing or being terminated.
Type | Limit | Description |
---|---|---|
Array Length | 1,000 | The maximum number of items allowed within a single array. |
Memory Allocation | 6MB | The maximum amount of memory a single UDF can be allocated. Exceeding this amount will result in early termination. |
Recursion | 1,000 | If any loop exceeds the recusion limit, the UDF will be terminated. |
Statements | 10,000 | The maximum number of declared statements. See here for more details. |
Duration | 5 seconds | The maximum amount of time a UDF execution can last before being terminated. |
Supported Features
Below is a comprehensive list of all features that are/not supported in the JavaScript UDFs.
ECMAScript 2015 (ES6)
- ✔ ArrayBuffer
- ✔ Arrow function expression
- ✔ Binary and octal literals
- ✔ Class support
- ✔ DataView
- ✔ Destructuring
- ✔ Default, rest and spread
- ✔ Enhanced object literals
- ✔ for...of
- ❌ Generators
- ✔ Template strings
- ✔ Lexical scoping of variables (let and const)
- ✔ Map and Set
- ✔ Modules and module loaders
- ✔ Promises (Experimental, API is unstable)
- ✔ Reflect
- ✔ Proxies
- ✔ Symbols
- ❌ Tail calls
- ✔ Typed arrays
- ✔ Unicode
- ✔ Weakmap and Weakset
ECMAScript 2016
- ✔ Array.prototype.includes
- ❌ await, async
- ✔ Block-scoping of variables and functions
- ✔ Exponentiation operator **
- ✔ Destructuring patterns (of variables)
ECMAScript 2017
- ✔ Object.values, Object.entries and Object.getOwnPropertyDescriptors
ECMAScript 2018
- ✔ Promise.prototype.finally
- ✔ Rest/spread operators for object literals (...identifier),
ECMAScript 2019
- ✔ Array.prototype.flat, Array.prototype.flatMap
- ✔ String.prototype.trimStart, String.prototype.trimEnd
- ✔ Object.fromEntries
- ✔ Symbol.description
- ✔ Optional catch binding
ECMAScript 2020
- ✔ BigInt
- ❌ export * as ns from
- ✔ for-in enhancements
- ✔ globalThis object
- ✔ import
- ✔ import.meta
- ✔ Nullish coalescing operator (??)
- ✔ Optional chaining
- ❌ Promise.allSettled
- ✔ String.prototype.matchAll
ECMAScript 2021
- ✔ Logical Assignment Operators (&&= ||= ??=)
- ✔ Numeric Separators (1_000)
- ✔ AggregateError
- ❌ Promise.any
- ✔ String.prototype.replaceAll
- ❌ WeakRef and FinalizationRegistry
ECMAScript 2022
- ❌ Class Fields
- ❌ RegExp Match Indices
- ❌ Top-level await
- ❌ Ergonomic brand checks for Private Fields
- ✔ .at()
- ✔ Accessible Object.prototype.hasOwnProperty (Object.hasOwn)
- ❌ Class Static Block
- ✔ Error Cause
ECMAScript Stage 3
- ✔ Array find from last
- ✔ ShadowRealm