Skip to content

ES5 Helper Reference ​

Overview ​

When writing TypeScript scripts in expressCode, your code is automatically transpiled to ES3-compatible ExtendScript. However, After Effects' ExtendScript engine (based on ES3) doesn't support many useful ES5 array and string methods.

expressCode solves this by:

  1. Transforming modern method calls into helper function calls
  2. Prepending non-polluting helper functions to your script

This allows you to write modern JavaScript while maintaining compatibility with After Effects' ES3 engine.

How It Works ​

Transformation Process ​

When you write TypeScript code using ES5 methods:

typescript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);

expressCode automatically transforms it to:

javascript
var numbers = [1, 2, 3, 4, 5];
var doubled = __es5_map(numbers, function(n) { return n * 2; });
var evens = __es5_filter(numbers, function(n) { return n % 2 === 0; });

The helper functions (__es5_map, __es5_filter, etc.) are then prepended to your script.

Non-Polluting Approach ​

Unlike some polyfill approaches that modify global prototypes (Array.prototype.map), expressCode uses standalone helper functions. This:

  • Avoids conflicts with existing code
  • Prevents prototype pollution
  • Maintains script isolation
  • Ensures consistent behavior

Supported Methods ​

Array Methods ​

map(callback, thisArg?) - Creates a new array with transformed elements

Creates a new array with the results of calling a function on every element.

TypeScript:

typescript
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);
// Result: [2, 4, 6]

Transforms to:

javascript
__es5_map(numbers, function(n) { return n * 2; })

Implementation:

javascript
function __es5_map(arr, callback, thisArg) {
    var len = arr.length >>> 0;
    var result = new Array(len);
    for (var k = 0; k < len; k++) {
        if (k in arr) {
            result[k] = callback.call(thisArg, arr[k], k, arr);
        }
    }
    return result;
}
filter(callback, thisArg?) - Creates a new array with elements that pass a test

Creates a new array with elements that pass a test.

TypeScript:

typescript
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(n => n % 2 === 0);
// Result: [2, 4]

Transforms to:

javascript
__es5_filter(numbers, function(n) { return n % 2 === 0; })

Implementation:

javascript
function __es5_filter(arr, callback, thisArg) {
    var len = arr.length >>> 0;
    var result = [];
    for (var k = 0; k < len; k++) {
        if (k in arr) {
            var val = arr[k];
            if (callback.call(thisArg, val, k, arr)) {
                result.push(val);
            }
        }
    }
    return result;
}
forEach(callback, thisArg?) - Executes a function for each array element

Executes a function once for each array element.

TypeScript:

typescript
const layers = comp.layers;
layers.forEach((layer, index) => {
  layer.name = "Layer " + (index + 1);
});

Transforms to:

javascript
__es5_forEach(layers, function(layer, index) {
  layer.name = "Layer " + (index + 1);
})

Implementation:

javascript
function __es5_forEach(arr, callback, thisArg) {
    var len = arr.length >>> 0;
    for (var k = 0; k < len; k++) {
        if (k in arr) {
            callback.call(thisArg, arr[k], k, arr);
        }
    }
}
reduce(callback, initialValue?) - Reduces array to a single value

Reduces an array to a single value by executing a reducer function.

TypeScript:

typescript
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, n) => acc + n, 0);
// Result: 10

Transforms to:

javascript
__es5_reduce(numbers, function(acc, n) { return acc + n; }, 0)

Implementation:

javascript
function __es5_reduce(arr, callback, initialValue) {
    var len = arr.length >>> 0;
    var k = 0;
    var value;

    if (arguments.length >= 3) {
        value = initialValue;
    } else {
        while (k < len && !(k in arr)) k++;
        if (k >= len) {
            throw new TypeError('Reduce of empty array with no initial value');
        }
        value = arr[k++];
    }

    while (k < len) {
        if (k in arr) {
            value = callback(value, arr[k], k, arr);
        }
        k++;
    }
    return value;
}
reduceRight(callback, initialValue?) - Reduces array from right to left

Same as reduce, but processes the array from right to left.

TypeScript:

typescript
const numbers = [1, 2, 3, 4];
const result = numbers.reduceRight((acc, n) => acc + n, 0);
// Result: 10

Transforms to:

javascript
__es5_reduceRight(numbers, function(acc, n) { return acc + n; }, 0)

Implementation:

javascript
function __es5_reduceRight(arr, callback, initialValue) {
    var len = arr.length >>> 0;
    var k = len - 1;
    var value;

    if (arguments.length >= 3) {
        value = initialValue;
    } else {
        while (k >= 0 && !(k in arr)) k--;
        if (k < 0) {
            throw new TypeError('Reduce of empty array with no initial value');
        }
        value = arr[k--];
    }

    while (k >= 0) {
        if (k in arr) {
            value = callback(value, arr[k], k, arr);
        }
        k--;
    }
    return value;
}
indexOf(searchElement, fromIndex?) - Returns first index of element

Returns the first index at which an element can be found.

TypeScript:

typescript
const colors = ["red", "green", "blue"];
const index = colors.indexOf("green");
// Result: 1

Transforms to:

javascript
__es5_indexOf(colors, "green")

Implementation:

javascript
function __es5_indexOf(arr, searchElement, fromIndex) {
    var len = arr.length >>> 0;
    var k = fromIndex ? (fromIndex | 0) : 0;
    if (k >= len) return -1;
    k = Math.max(k >= 0 ? k : len - Math.abs(k), 0);
    while (k < len) {
        if (k in arr && arr[k] === searchElement) return k;
        k++;
    }
    return -1;
}
lastIndexOf(searchElement, fromIndex?) - Returns last index of element

Returns the last index at which an element can be found.

TypeScript:

typescript
const numbers = [1, 2, 3, 2, 1];
const index = numbers.lastIndexOf(2);
// Result: 3

Transforms to:

javascript
__es5_lastIndexOf(numbers, 2)

Implementation:

javascript
function __es5_lastIndexOf(arr, searchElement, fromIndex) {
    var len = arr.length >>> 0;
    var k = fromIndex !== undefined ? (fromIndex | 0) : len - 1;
    k = k >= 0 ? Math.min(k, len - 1) : len - Math.abs(k);
    while (k >= 0) {
        if (k in arr && arr[k] === searchElement) return k;
        k--;
    }
    return -1;
}
every(callback, thisArg?) - Tests if all elements pass a test

Tests whether all elements pass a test.

TypeScript:

typescript
const numbers = [2, 4, 6, 8];
const allEven = numbers.every(n => n % 2 === 0);
// Result: true

Transforms to:

javascript
__es5_every(numbers, function(n) { return n % 2 === 0; })

Implementation:

javascript
function __es5_every(arr, callback, thisArg) {
    var len = arr.length >>> 0;
    for (var k = 0; k < len; k++) {
        if (k in arr && !callback.call(thisArg, arr[k], k, arr)) {
            return false;
        }
    }
    return true;
}
some(callback, thisArg?) - Tests if at least one element passes a test

Tests whether at least one element passes a test.

TypeScript:

typescript
const numbers = [1, 3, 5, 6];
const hasEven = numbers.some(n => n % 2 === 0);
// Result: true

Transforms to:

javascript
__es5_some(numbers, function(n) { return n % 2 === 0; })

Implementation:

javascript
function __es5_some(arr, callback, thisArg) {
    var len = arr.length >>> 0;
    for (var k = 0; k < len; k++) {
        if (k in arr && callback.call(thisArg, arr[k], k, arr)) {
            return true;
        }
    }
    return false;
}

String Methods ​

trim() - Removes whitespace from both ends

Removes whitespace from both ends of a string.

TypeScript:

typescript
const text = "  hello world  ";
const trimmed = text.trim();
// Result: "hello world"

Transforms to:

javascript
__es5_trim(text)

Implementation:

javascript
function __es5_trim(str) {
    return str.replace(/^\s+|\s+$/g, '');
}
trimLeft() - Removes whitespace from the beginning

Removes whitespace from the beginning of a string.

TypeScript:

typescript
const text = "  hello world  ";
const trimmed = text.trimLeft();
// Result: "hello world  "

Transforms to:

javascript
__es5_trimLeft(text)

Implementation:

javascript
function __es5_trimLeft(str) {
    return str.replace(/^\s+/, '');
}
trimRight() - Removes whitespace from the end

Removes whitespace from the end of a string.

TypeScript:

typescript
const text = "  hello world  ";
const trimmed = text.trimRight();
// Result: "  hello world"

Transforms to:

javascript
__es5_trimRight(text)

Implementation:

javascript
function __es5_trimRight(str) {
    return str.replace(/\s+$/, '');
}

Usage Examples ​

Example 1: Processing Layers ​

typescript
// Get all visible layers
const comp = app.project.activeItem as CompItem;
const allLayers: Layer[] = [];
for (let i = 1; i <= comp.numLayers; i++) {
  allLayers.push(comp.layer(i));
}

const visibleLayers = allLayers.filter(layer => layer.enabled);

// Apply effect to each visible layer
visibleLayers.forEach(layer => {
  const effect = (layer as AVLayer).effect.addProperty("ADBE Gaussian Blur 2");
  (effect.property("Blurriness") as OneDProperty).setValue(10);
});

Example 2: Finding Layers by Name ​

typescript
const comp = app.project.activeItem as CompItem;
const layerNames: string[] = [];
for (let i = 1; i <= comp.numLayers; i++) {
  layerNames.push(comp.layer(i).name);
}

const targetName = "Shape Layer 1";
const index = layerNames.indexOf(targetName);

if (index !== -1) {
  alert("Found layer at index: " + (index + 1));
}

Example 3: Calculating Statistics ​

typescript
const comp = app.project.activeItem as CompItem;
const durations: number[] = [];
for (let i = 1; i <= comp.numLayers; i++) {
  durations.push(comp.layer(i).outPoint - comp.layer(i).inPoint);
}

const totalDuration = durations.reduce((sum, d) => sum + d, 0);
const avgDuration = totalDuration / durations.length;

alert("Average layer duration: " + avgDuration + " seconds");

Example 4: Validating Layer Properties ​

typescript
const comp = app.project.activeItem as CompItem;
const layers: Layer[] = [];
for (let i = 1; i <= comp.numLayers; i++) {
  layers.push(comp.layer(i));
}

// Check if all layers are within comp bounds
const allInBounds = layers.every(layer => {
  const pos = layer.property("ADBE Transform Group")
    .property("ADBE Position") as Property;
  const value = pos.value as [number, number];
  return value[0] >= 0 && value[0] <= comp.width &&
         value[1] >= 0 && value[1] <= comp.height;
});

if (!allInBounds) {
  alert("Some layers are outside composition bounds!");
}

Important Notes ​

Only in TypeScript Script Mode ​

ES5 transforms are only applied in TypeScript Script mode, not in:

  • JavaScript Script mode (assumes you're writing ES3-compatible code)
  • Expression mode (expressions have different constraints)

Automatic Transformation ​

You don't need to do anything special:

  1. Write TypeScript code using ES5 methods
  2. Click "Run Script"
  3. expressCode automatically transforms and prepends helpers
  4. The script runs in After Effects

Performance Considerations ​

The helper functions are optimized implementations that closely match ES5 specifications. However, for very large arrays (1000+ elements), consider:

  • Using traditional for loops for maximum performance
  • Breaking operations into smaller chunks
  • Caching results when possible

Compatibility ​

These transforms work in all versions of After Effects that support ExtendScript (CS3 and later). The generated code is pure ES3 and doesn't require any modern JavaScript features.

See Also ​

expressCode v1.2.3 Documentation