Enhance Your ServiceNow Pro-Code Skills with ES6 Script Includes

Reece PoulsenReece Poulsen
9 min read
๐Ÿ˜‰
ES6 class-based Script Includes can set you up to have developer superpowers. If you don't believe me then check out the VS Code IntelliSense Superpowers section near the end of this post!

EcmaScript 6 (ES6) was released in 2015 and has been the standard for JavaScript on the web for almost a decade. ServiceNow's Tokyo release in 2022 introduced a new scripting mode for scoped apps, ECMAScript 2021 (ES12), which enables many ES6 features in server-side scripting.

In ServiceNow, developers interact with the server by writing JavaScript code that uses APIs like GlideRecord. This has offered a fairly modern developer experience until ES6 came along. Since then, ServiceNow JavaScript developers have been limited to using ES5 while the rest of the web has moved on to ES6. It took ServiceNow 7 years to introduce any form of ES6 support. Why was there such a delay?

I started writing server-side code on ServiceNow just over a year ago and was surprised to see var used everywhere! In college, I learned ES6 and got used to using const and let. It felt odd to switch back to writing ES5 when I was so comfortable with ES6 JavaScript. When I found out that ServiceNow had an ES6 mode, I immediately started experimenting with it. It has been an interesting journey over the past year, and I want to share some things that have helped improve my developer experience since then. But first, let's explore how ES6 support was introduced for ServiceNow and why it's such a significant advancement.

ServiceNow's Implementation of ES6 on top of Rhino

ServiceNow's backend code is written in Java and it relies on a Java engine called Rhino to serve as a connection between JavaScript server-side code and the Java backend. The Rhino version used by ServiceNow supports ES5 JavaScript but not ES6. With the release of ES6, ServiceNow had to create a translation layer to convert new ES6 features into ES5 JavaScript. This task was quite challenging, leading to a delay in implementation.

A simple diagram of ServiceNow interacting with Rhino

This layer created by ServiceNow uses a combination of transpilation and polyfill techniques to convert ES6 behavior into ES5. It has a few noteworthy side-effects that should be mentioned:

  • Not all ES6 features are supported. Here is a list of which ones are.

  • Supported server-side ES6 features don't always behave exactly the same in ServiceNow as they would elsewhere on the web.

  • Any ServiceNow client-side code can fully leverage all ES6 features because it runs locally in the user's browser.

What is the difference between a polyfill and transpiler?
A polyfill will try to emulate certain APIs, so [you] can use them as if they were already implemented. A transpiler on the other hand will transform your code and replace the respective code section by other code, which can already be executed. StackOverflow Post

ES6 JavaScript Class Breakdown

Now that you have a high-level understanding of how ServiceNow implemented ES6, lets take a look at how it can be used to create an ES6 class-based script include.

๐Ÿ“ข
ServiceNow requires that the name of your Script Include and the class declared within it matches up.
class ES6Example {
    static staticVar = "Hello world";

    static staticMethod(param1) {
        // I can be called without initializing the class
    }

    constructor(createdBy) {
        // Set some initial states
        this.createdBy = createdBy;
        this.createdOn = new GlideDateTime();
    }

    doSomething(param1) {
        // This method does something
    }

    doSomethingElse(param1, param2, param3) {
        // This method does something else...use your imagination
    }

    type = `ES6Example`;
}

This demonstrates how to declare:

  • The class: class ClassName

  • Static properties: static propName = value

  • Static methods: static methodName(param1) {...}

  • A constructor: constructor(param1)

  • Methods: methodName(param1)

  • Properties: propName = value

It can be helpful to think of a class as a container of functions (referred to as methods within a class) and attributes. Static methods and attributes can be accessed through the class without needing initialization. Non-static methods and attributes need the class to be initialized before they can be used.

Here is how you can create an instance of your class using the new keyword:

const myClassInstance = new ES6Example("Test");

This type of class can be extended using this syntax:

class ES6Example_Extended extends ES6Example {
    constructor(param1) {
        // Call the parent class' constructor and pass through parameters
        super(...arguments);
    }

    doSomething() {
        // Overrides the original doSomething method in the original class
    }

    type = 'ES6Example_Extended';
};

Normal ServiceNow Script Include Breakdown

Now, lets compare the ES6 class above to a normal ServiceNow Script Include class.

var DefaultExample = Class.create();
DefaultExample.prototype = {
    staticVar: "Hello world",

    staticMethod: function (param1) {
        // I can be called without initializing the class
    },

    initialize: function (createdBy) {
        // Set some initial states
        this.createdBy = createdBy;
        this.createdOn = new GlideDateTime();
    },

    doSomething: function (param1) {
        // This method does something
    },

    doSomethingElse: function (param1, param2, param3) {
        // This method does something else...use your imagination
    },

    type: 'DefaultExample'
};

There are a couple of key differences:

  • ServiceNow's special Class.create() method combined with modifying the returned object's prototype

  • Methods and attributes are added as key-value pairs to the object's prototype

    • This means each one has to be followed by a comma
  • The use of an initialize method rather than a constructor

ServiceNow's server-side scripting has existed longer than JavaScript classes. In order to replicate class features in JavaScript, the ServiceNow team devised a pseudo class using the Class.create() method combined with a requirement to modify the returned object's prototype. This unique implementation of JavaScript classes is exclusive to the ServiceNow ecosystem and is not industry standard.

An instance of this kind of class is created in the same way as an ES6 class:

var myClassInstance = new DefaultExample("Test");

And can be extended using the Object.extendsObject method:

var DefaultExample_Extended = Class.create();
DefaultExample_Extended.prototype = Object.extendsObject(DefaultExample, {

    doSomething: function () {
        // Overrides the original doSomething method in the original class
    },

    type: 'DefaultExample_Extended'
});
๐Ÿ’ก
Notice that there isn't an initialize method in the extended class. If it was declared here then it would completely override the parent class' initialize method.

How to Convert a Script Include to an ES6 Class

Converting a normal ServiceNow Script Include to an ES6 class is relatively easy:

  1. Make sure that your application record is in ES Latest mode

  2. Remove the Class.create() call

  3. Swap the ClassName.prototype = {...} line with a class declaration like so class MyClass() {...}

  4. Replace the key: value declaration syntax for properties and methods to the ES6 class declaration syntax

    1. Change any properties from propName: value to propName = value

    2. Change any methods from methodName: function(param1) {...} to methodName(param1) {...}

    3. Remove all of the commas after each declaration

  5. Replace the initialize method with a constructor

๐Ÿ†
Any code that calls your script include does not have to change!

VS Code IntelliSense Superpowers

Alright, the moment you have all been waiting for, let's take a look at how all of this, combined with some other tools, can give you ServiceNow development superpowers. Here are some brief introductions to the tools that we are going to be using:

VS Code
Visual Studio Code, also commonly referred to as VS Code, is a source-code editor developed by Microsoft for Windows, Linux, macOS and web browsers. Features include support for debugging, syntax highlighting, intelligent code completion, snippets, code refactoring, and embedded version control with Git. Users can change the theme, keyboard shortcuts, preferences, and install extensions that add functionality. (Wikipedia)
SNICH Extension
ServiceNow Integrated Code Helper (SNICH) bridges the gap between a ServiceNow instance and VS Code. It allows you to sync ServiceNow files to your local development environment so that you can leverage modern developer tools like IntelliSense, AI auto-complete, and other rich IDE features. It also includes auto-complete capabilities for common ServiceNow APIs like GlideRecord. Shout-out to my co-worker Nate Anderson for creating this awesome extension that I use every day!
JSDoc Method Headers
JSDoc is a markup language used to annotate JavaScript source code files. Using comments containing JSDoc, programmers can add documentation describing the application programming interface of the code they're creating. This is then processed, by various tools, to produce documentation in accessible formats like HTML and Rich Text Format. (Wikipedia)

Now let's get setup:

  1. Make sure that you have VS Code installed (Install here)

  2. Go to the extensions menu and install S.N.I.C.H.

  3. Open the VS Code command pallet (cmd or control + shift + p) and run the SNICH: Setup a New Instance command and enter your instance details:

    1. Instance name (from the URL)

    2. Authentication method (usually basic auth is good enough here)

    3. Username and password

  4. Once a connection to your instance is established you can run the SNICH: Load all Application Files (Pull) command to pull script files from an app scope into your local machine. The default configuration pulls:

    1. Business Rules (sys_script)

    2. Script Includes (sys_script_include)

    3. Client Scripts (sys_script_client)

    4. UI Actions (sys_ui_action)

Once you've completed these setup steps, you are ready to begin developing ServiceNow scripts in VS Code! This might be a new experience for those accustomed to developing on the platform, so there could be a slight learning curve, but it's worth it! Let's take a look at some examples of these superpowers in action.

VS Code + SNICH

  • Loading application files and making a change to a Business Rule:

  • IntelliSense with GlideRecord:

  • IntelliSense with GlideDateTime and other ServiceNow APIs:

VS Code + SNICH + ES6 Class-based Script Includes + JSDoc

IntelliSense with ES6 Script Include Methods + JSDoc Method Header:

Autocomplete with an ES6 Script Include versus no autocomplete with a standard ServiceNow Script Include (JSDoc Method headers work on both, but they work better on ES6 classes):

Using VS Code's JavaScript codelens setting to see class method references (Open VS Code's settings menu with cmd or control + ,) :


Conclusion

With the help of the right tools, writing code on the ServiceNow platform can become a much more modern developer experience! Gone are the days of being restricted by ServiceNow's built-in script editor, let's see what you can do!


Resources

0
Subscribe to my newsletter

Read articles from Reece Poulsen directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Reece Poulsen
Reece Poulsen

Back in my freshman year of college, I was introduced to the world of programming, and it immediately caught my attention. The idea of creating something new with just a little learning and a couple of lines of code fascinated meโ€”it was like discovering a whole new universe of possibilities! Ever since that moment, I've been on a continuous journey to expand my programming knowledge and skills. Now I'm a relatively new software developer on the ServiceNow platform, and I'm eager to explore its potential. Through this blog, I hope to share some of the things I'm learning along the way. Let's dive into the world of ServiceNow together and uncover the tricks and insights that can make a difference for us as developers!