User Guide Cancel

Syntax differences between expression engines

  1. After Effects User Guide
  2. Beta releases
    1. Beta Program Overview
    2. After Effects Beta Home
  3. Getting started
    1. Get started with After Effects
    2. What's new in After Effects 
    3. Release Notes | After Effects
    4. After Effects system requirements
    5. Keyboard shortcuts in After Effects
    6. Supported File formats | After Effects
    7. Hardware recommendations
    8. After Effects for Apple silicon
    9. Planning and setup
  4. Workspaces
    1. General user interface items
    2. Get to know After Effects interface
    3. Workflows
    4. Workspaces, panels, and viewers
  5. Projects and compositions
    1. Projects
    2. Composition basics
    3. Precomposing, nesting, and pre-rendering
    4. View detailed performance information with the Composition Profiler
    5. CINEMA 4D Composition Renderer
  6. Importing footage
    1. Preparing and importing still images
    2. Importing from After Effects and Adobe Premiere Pro
    3. Importing and interpreting video and audio
    4. Preparing and importing 3D image files
    5. Importing and interpreting footage items
    6. Working with footage items
    7. Detect edit points using Scene Edit Detection
    8. XMP metadata
  7. Text and Graphics
    1. Text
      1. Formatting characters and the Character panel
      2. Text effects
      3. Creating and editing text layers
      4. Formatting paragraphs and the Paragraph panel
      5. Extruding text and shape layers
      6. Animating text
      7. Examples and resources for text animation
      8. Live Text Templates
    2. Motion Graphics
      1. Work with Motion Graphics templates in After Effects
      2. Use expressions to create drop-down lists in Motion Graphics templates
      3. Work with Essential Properties to create Motion Graphics templates
      4. Replace images and videos in Motion Graphics templates and Essential Properties
      5. Animate faster and easier using the Properties panel
  8. Drawing, Painting, and Paths
    1. Overview of shape layers, paths, and vector graphics
    2. Paint tools: Brush, Clone Stamp, and Eraser
    3. Taper shape strokes
    4. Shape attributes, paint operations, and path operations for shape layers
    5. Use Offset Paths shape effect to alter shapes
    6. Creating shapes
    7. Create masks
    8. Remove objects from your videos with the Content-Aware Fill panel
    9. Roto Brush and Refine Matte
  9. Layers, Markers, and Camera
    1. Selecting and arranging layers
    2. Blending modes and layer styles
    3. 3D layers
    4. Layer properties
    5. Creating layers
    6. Managing layers
    7. Layer markers and composition markers
    8. Cameras, lights, and points of interest
  10. Animation, Keyframes, Motion Tracking, and Keying
    1. Animation
      1. Animation basics
      2. Animating with Puppet tools
      3. Managing and animating shape paths and masks
      4. Animating Sketch and Capture shapes using After Effects
      5. Assorted animation tools
      6. Work with Data-driven animation
    2. Keyframe
      1. Keyframe interpolation
      2. Setting, selecting, and deleting keyframes
      3. Editing, moving, and copying keyframes
    3. Motion tracking
      1. Tracking and stabilizing motion
      2. Face Tracking
      3. Mask Tracking
      4. Mask Reference
      5. Speed
      6. Time-stretching and time-remapping
      7. Timecode and time display units
    4. Keying
      1. Keying
      2. Keying effects
  11. Transparency and Compositing
    1. Compositing and transparency overview and resources
    2. Alpha channels and masks
    3. Track Mattes and Traveling Mattes
  12. Adjusting color
    1. Color basics
    2. Color management
    3. Color Correction effects
    4. OpenColorIO and ACES color management
  13. Effects and Animation Presets
    1. Effects and animation presets overview
    2. Effect list
    3. Effect Manager
    4. Simulation effects
    5. Stylize effects
    6. Audio effects
    7. Distort effects
    8. Perspective effects
    9. Channel effects
    10. Generate effects
    11. Time effects
    12. Transition effects
    13. The Rolling Shutter Repair effect
    14. Blur and Sharpen effects
    15. 3D Channel effects
    16. Utility effects
    17. Matte effects
    18. Noise and Grain effects
    19. Detail-preserving Upscale effect
    20. Obsolete effects
  14. Expressions and Automation
    1. Expressions
      1. Expression basics
      2. Understanding the expression language
      3. Using expression controls
      4. Syntax differences between the JavaScript and Legacy ExtendScript expression engines
      5. Editing expressions
      6. Expression errors
      7. Using the Expressions editor
      8. Use expressions to edit and access text properties
      9. Expression language reference
      10. Expression examples
    2. Automation
      1. Automation
      2. Scripts
  15. Immersive video, VR, and 3D
    1. Construct VR environments in After Effects
    2. Apply immersive video effects
    3. Compositing tools for VR/360 videos
    4. Advanced 3D Renderer
    5. Import and add 3D models to your composition
    6. Import 3D models from Creative Cloud Libraries
    7. Image-Based Lighting
    8. Extract and animate lights and cameras from 3D models
    9. Tracking 3D camera movement
    10. Cast and accept shadows
    11. Embedded 3D model animations
    12. Shadow Catcher
    13. 3D depth data extraction
    14. Modify materials properties of a 3D layer
    15. Work in 3D Design Space
    16. 3D Transform Gizmos
    17. Do more with 3D animation
    18. Preview changes to 3D designs real time with the Mercury 3D engine
    19. Add responsive design to your graphics 
  16. Views and Previews
    1. Previewing
    2. Video preview with Mercury Transmit
    3. Modifying and using views
  17. Rendering and Exporting
    1. Basics of rendering and exporting
    2. H.264 Encoding in After Effects
    3. Export an After Effects project as an Adobe Premiere Pro project
    4. Converting movies
    5. Multi-frame rendering
    6. Automated rendering and network rendering
    7. Rendering and exporting still images and still-image sequences
    8. Using the GoPro CineForm codec in After Effects
  18. Working with other applications
    1. Dynamic Link and After Effects
    2. Working with After Effects and other applications
      1. Export After Effects project as Premiere Pro project
    3. Sync Settings in After Effects
    4. Creative Cloud Libraries in After Effects
    5. Plug-ins
    6. Cinema 4D and Cineware
  19. Collaboration: Frame.io, and Team Projects
    1. Collaboration in Premiere Pro and After Effects
    2. Frame.io
      1. Install and activate Frame.io
      2. Use Frame.io with Premiere Pro and After Effects
      3. Frequently asked questions
    3. Team Projects
      1. Get Started with Team Projects
      2. Create a Team Project
      3. Collaborate with Team Projects
  20. Memory, storage, performance
    1. Memory and storage
    2. How After Effects handles low memory issues while previewing    
    3. Improve performance
    4. Preferences
    5. GPU and GPU driver requirements for After Effects
  21. Knowledge Base
    1. Known issues
    2. Fixed issues
    3. Frequently asked questions
    4. After Effects and macOS Ventura
    5. How After Effects handles low memory issues while previewing

This document explains the expression language syntax differences between the JavaScript and Legacy ExtendScript expression engines in After Effects 16.0.

Refer to this document to learn how to improve your expressions for the JavaScript expression engine, or when fixing errors that occur when expressions written for previous releases of After Effects fail to evaluate in the JavaScript expression engine.

The expression language in After Effects is based on JavaScript, which is an implementation of ECMAScript. The JavaScript expression engine in After Effects 16.0 is based on ECMAScript 2018. The Legacy ExtendScript expression engine is based on ECMAScript 3 (1999). (Adobe ExtendScript is also the language used for scripting in After Effects and other Adobe applications.)

You can follow the examples provided below, as well as guidance for how to author expressions that work in both the JavaScript and Legacy ExtendScript expression engines.

The core differences between the JavaScript and Legacy ExtendScript expression engines are:

Modern JavaScript syntax: Improvements made to the expression language

Expressions can use JavaScript syntax from ECMAScript 2018

Many additions have been made to the JavaScript language since ECMAScript 3. There are new methods to use with strings, arrays, and objects which are more compact and readable. There are also new ways to declare variables and functions, as well as default parameters, spread operators and more. This document does not cover these changes, as they are general to the JavaScript language. Resources for learning about the many syntax additions can be found at the following links:

Additional recommended, in-depth resources for learning JavaScript:

.value is no longer required when linking to other properties from Source Text

When referencing another property value from a Source Text property, the Legacy ExtendScript engine requires .value to be added at the end of the property. The JavaScript engine shows the value of the property by default unless another attribute like .propertyIndex or .name is explicitly used.

For example:

thisComp.layer("Solid 1").transform.position
 
// In the Legacy engine, this evaluates to "[object Property]" when applied to a Source Text property.
// In the JavaScript engine, this evaluates to the value of the Position property of layer "Solid 1" when applied to a Source Text property.

Freezing property values with posterizeTime(0)

In After Effects 16.0, posterizeTime(0) freezes the property value at time 0 in the composition. This applies to both the JavaScript and Legacy ExtendScript engines.

Note:

This is not backward-compatible and may cause unexpected results in After Effects versions prior to 16.0.

Incompatible Legacy Syntax

Nearly all of the expression syntax from the Legacy ExtendScript expression engine is forward-compatible with the JavaScript expression engine. However, there is some legacy syntax which is not compatible with the JavaScript expression engine. Sometimes this is caused by syntax changes in modern JavaScript. In other cases, obsolete or outdated syntax has been removed. Examples of non-working and working syntax are provided below.

Most of these syntax difference can be corrected via application scripting that re-writes the expressions.

if...else syntax differences

In general, it is recommended to always write if...else statements with line breaks and brackets in accordance with MDN guidelines. The Legacy ExtendScript engine was tolerant of loose syntax in if...else statements, however the JavaScript engine is strict. Incorrect if...else syntax fails to evaluate when using the JavaScript engine.

Ending an expression in an if statement without an else is not allowed

When an expression ends with an if statement without an else statement, the JavaScript engine will fail to evaluate the expression with the error "Undefined value used in expression (could be an out of range array subscript?)". In the Legacy ExtendScript engine, the following expression evaluates to 100 if the time is greater than 1 second, else it evaluates to 50:

var x = 50;
if ( time > 1 ) {
    x = 100
}
// The "else" here is implied but not stated.

The JavaScript engine needs the else portion of the statement to be explicitly stated if it is the last statement in the expression:

var x = 50;
if ( time > 1 ) {
    x = 100;
} else {
    x;
}

This will evaluate correctly in both the JavaScript engine and the Legacy ExtendScript engine.

if and else cannot be on the same line without brackets

An if...else statement on a single line without brackets evaluates in the Legacy ExtendScript engine, but fails to evaluate in the JavaScript engine with an error such as "Syntax Error: Unexpected token else" or "Undefined value used in expression (could be an out of range array subscript?)". The error varies, depending on the context and property type.

In the Legacy ExtendScript engine, the following expression evaluates to 100 if the time is greater than 1 second, else it evaluates to 50:

if ( time > 1 ) 100 else 50;

The JavaScript engine requires line breaks or brackets to evaluate if...else statements. For simple cases, the ternary operator may be used instead. Any of the following syntax can be used with the JavaScript engine:

// Solution A: adding a line break before "else" will allow both engines to evaluate correctly.
 
if ( time > 1 ) 100
else 50;
 
// Solution B: adding correct bracketing will also allow both engines to evaluate correctly.
 
if ( time > 1 ) { 100 } else { 50 };
 
// Solution C: Use a ternary operator in place of the if...else statement, which also evaluates correctly in both engines.
 
time > 1 ? 100 : 50;

All of the above solutions evaluate correctly in both the JavaScript engine and the Legacy ExtendScript engine.

Expressions cannot end in a function declaration

If an expression ends with a function declaration, the JavaScript engine fails to evaluate the expression with the error "Object of type found where a Number, Array, or Property is needed". In the JavaScript engine, the last item evaluated must return a value, rather than declare one.

The following example works in the Legacy engine, but not the JavaScript engine:

timesTen( value );  // The Legacy engine evaluates this line, even though the function is declared below.
 
function timesTen ( val ) {
    return val * 10
}

When a function is called as the last line (instead of the declaration), the expression will evaluate correctly in both engines:

function timesTen ( val ) {
    return val * 10
}
 
timesTen( value );  // The JavaScript engine needs the function call to happen below the declaration in order to return the correct value.

this() shorthand syntax is not allowed; use thisLayer() instead

In the Legacy ExtendScript engine, this was allowed to be used as shorthand for thisLayer. In the JavaScript engine, this refers to the global object and thisLayer must be used instead. Using this in the JavaScript engine will usually result in the error "this is not a function".

In the following Legacy ExtendScript example, this is used to create a compact link to a Text Layer Position property from the Source Text property:

this(5)(2).value;

In the JavaScript engine, this must be replaced by thisLayer:

thisLayer(5)(2).value;

Using thisLayer is compatible with both expression engines.

Source Text property array-index access to characters requires .value

In the Legacy ExtendScript expression engine, the characters of a text property could be accessed with bracket notation like an array:

text.sourceText[0]      // Returns the first character of the Source Text property's text value.

In the JavaScript engine, .value must be added in order to access the characters:

text.sourceText.value[0]    // Returns the first character of the Source Text property's text value.

This syntax is compatible with both engines.

Snake case properties and methods are not allowed

The deprecated snake case properties and methods (written with an underscore instead of camelCase) are not supported by the JavaScript engine. The camelCase versions should be used instead as they are compatible with both engines. The following is a list of the deprecated snake case and their corresponding camelCase.

Snake case properties

camelCase properties

Snake Case methods

camelCase Methods

this_comp

this_layer

this_property

color_depth

has_parent

in_point

out_point

start_time

has_video

has_audio

audio_active

anchor_point

audio_levels

time_remap

casts_shadows

light_transmission

accepts_shadows

accepts_lights

frame_duration

shutter_angle

shutter_phase

num_layers

pixel_aspect

point_of_interest

depth_of_field

focus_distance

blur_level

cone_angle

cone_feather

shadow_darkness

shadow_diffusion

active_camera

thisComp

thisLayer

thisProperty

colorDepth

hasParent

inPoint

outPoint

startTime

hasVideo

hasAudio

audioActive

anchorPoint

audioLevels

timeRemap

castsShadows

lightTransmission

acceptsShadows

acceptsLights

frameDuration

shutterAngle

shutterPhase

numLayers

pixelAspect

pointOfInterest

depthOfField

focusDistance

blurLevel

coneAngle

coneFeather

shadowDarkness

shadowDiffusion

activeCamera

value_at_time()

velocity_at_time()

speed_at_time()

nearest_key()

posterize_time()

look_at()

seed_random()

gauss_random()

ease_in()

ease_out()

rgb_to_hsl()

hsl_to_rgb()

degrees_to_radians()

radians_to_degrees()

from_comp_to_surface()

to_comp_vec()

from_comp_vec()

to_world_vec()

from_world_vec()

to_comp()

from_comp()

to_world()

from_world()

temporal_wiggle()

loop_in_duration()

loop_out_duration()

loop_in()

loop_out()

valueAtTime()

velocityAtTime()

speedAtTime()

nearestKey()

posterizeTime()

lookAt()

seedRandom()

gaussRandom()

easeIn()

easeOut()

rgbToHsl()

hslToRgb()

degreesToRadians()

radiansToDegrees()

fromCompToSurface()

toCompVec()

fromCompVec()

toWorldVec()

fromWorldVec()

toComp()

fromComp()

toWorld()

fromWorld()

temporalWiggle()

loopInDuration()

loopOutDuration()

loopIn()

loopOut()

Using eval() with binary-encoded (.jsxbin) expressions

Expressions encoded in the ExtendScript binary format (saved as a binary .jsxbin file from ExtendScript ToolKit CC) are not supported by the JavaScript engine.

If you want to obfuscate an expression, use the Legacy ExtendScript engine or use a different obfuscation method that is compatible with ECMAScript 2018. Some obfuscation methods might not be compatible with both expression engines.

Limited support for the $. (Dollar) object

The $. (Dollar) object methods and properties are specific to ExtendScript and mostly not supported in the JavaScript engine. This table lists unsupported and supported uses of the $. (Dollar) object:

Unsupported $.

Supported $.

$.fileName

$.hiResTimes

$.stack

$.evalFile()

$.list()

$.setenv()

$.getenv()

$.appEncoding

$.buildDate

$.decimalPoint

$.dictionary

$.error

$.flags

$.includePath

$.level

$.line

$.locale

$.localize

$.memCache

$.os

$.screens

$.strict

$.version

$.build

$.engineName (this is unsupported in the Legacy ExtendScript engine)

$.global

No support for ...reflect.properties, ...reflect.methods, and toSource()

reflect.properties and reflect.methods are not supported in the JavaScript engine; they are ExtendScript-specific methods which have no direct equivalent in JavaScript.

toSource() in JavaScript has been deprecated and is not part of any standards track.

To see a list of available properties and methods for any given After Effects property similar to what was provided by the above methods, use the following expression on a Source Text property and link it to your desired property, for example, using the pick whip in place of thisProperty on line 1:

let obj = thisProperty;     // Replace "thisProperty" with a property-link to your desired property.
let props = [];
 
do {
    Object.getOwnPropertyNames(obj).forEach(prop => {
        if (props.indexOf(prop) === -1) {
            props.push(prop);
        }
    });
} while (obj = Object.getPrototypeOf(obj));
 
props.join("\n");           // Returns an array of strings listing the properties and methods available.

The above expression is not compatible with the Legacy ExtendScript engine. It uses syntax and methods not available in ECMAScript 3.

Syntax Requirements for .jsx Expression Libraries and eval() with the JavaScript Engine

When using expressions inside a .jsx expression function library or when an expression is called inside eval(), certain syntax needs to be modified:

An explicit thisLayer. or thisProperty. prefix needs to be added to any native method or attribute which is not explicitly called on a layer or property. The prefix tells the JavaScript engine which object you are calling the method or attribute on.

Math operations on array values like Position needs to be calculated using vector math or by using looping functions to act on every item in the array. Overloaded math operators like position + [100,100] will not evaluate.

When using the JavaScript engine, expressions are pre-processed before evaluation in order to make some of the Legacy ExtendScript expression syntax readable by the new engine. However, these pre-processing tasks are not performed when evaluating expressions from a .jsx expression function library or when an expression is called inside eval(). The above syntax modifications must be made manually for these cases. All of these syntax modifications are backward-compatible with the Legacy ExtendScript engine, so a .jsx expression library written to work with the JavaScript engine will also work with the Legacy ExtendScript engine.

Performance tip: Due to the lack of pre-processing, calling complex expressions from a .jsx library with this syntax and the JavaScript engine may see a performance improvement, compared to calling the same expression directly on a property.

Explicitly prefix native methods and attributes with thisLayer. or thisProperty.

The following table lists the methods and attributes that require a prefix. For example, time must be written as thisLayer.time, while wiggle() must be written as thisProperty.wiggle()

These prefixes are only required in cases when the attribute or method isn't already being explicitly called on another layer or property. For instance, when calling thisComp.layer(1).hasParent, adding thisLayer. is not required because .hasParent is already being explicitly called on layer(1).

Methods Requiring thisLayer.

Attributes Requiring thisLayer.

Methods Requiring thisProperty.

Attributes Requiring thisProperty.

comp()
footage()
posterizeTime()
add()
sub()
mul()
div()
clamp()
length()
dot()
normalize()
cross()
lookAt()
timeToFrames()
framesToTime()
timeToTimecode()
timeToFeetAndFrames()
timeToNTSCTimecode()
timeToCurrentFormat()
seedRandom()
random()
gaussRandom()
noise()
degreesToRadians()
radiansToDegrees()
linear()
ease()
easeIn()
easeOut()
rgbToHsl()
hslToRgb()
hexToRgb()
mask()
sourceRectAtTime()
sourceTime()
sampleImage()
toComp()
fromComp()
toWorld()
fromWorld()
toCompVec()
fromCompVec()
toWorldVec()
fromWorldVec()
fromCompToSurface()

time
source
thisProject
colorDepth
transform
anchorPoint
position
scale
rotation
opacity
orientation
rotationX
rotationY
rotationZ
lightTransmission
castsShadows
acceptsShadows
acceptsLights
ambient
diffuse
specular
specularIntensity
shininess
specularShininess
metal
audioLevels
timeRemap
marker
name
width
height
index
parent
hasParent
inPoint
outPoint
startTime
hasVideo
hasAudio
active
enabled
audioActive
cameraOption
pointOfInterest
zoom
depthOfField
focusDistance
aperature
blurLevel
irisShape
irisRotation
irisRoundness
irisAspectRatio
irisDiffractionFringe
highlightGain
highlightThreshold
highlightSaturation
lightOption
intensity
color
coneAngle
coneFeather
shadowDarkness
shadowDiffusion

valueAtTime()
velocityAtTime()
speedAtTime()
wiggle()
temporalWiggle()
smooth()
loopIn()
loopOut()
loopInDuration()
loopOutDuration()
key()
nearestKey()
propertyGroup()
points()
inTangents()
outTangents()
isClosed()
pointsOnPath()
tangentOnPath()
normalOnPath()
createPath()

velocity
speed
numKeys
propertyIndex

Replacing math operators with vector math functions

Both the JavaScript and LegacyExtendScript engines allow overloading math operators for arrays by using syntax like position + [100,100], but this does not work for expressions inside a .jsx expression function library or inside eval().

In order to perform math on array properties like Position, Scale, etc., the vector math equivalents should be used for addition, subtraction, multiplication, and division. The vector math functions will also work for regular numbers, so a function which might be called on properties of either data type should use the vector math functions.

Note:

The thisLayer. prefix must be used with the vector math functions.

  • Addition: thisLayer.add(vec1, vec2)
  • Subtraction: thisLayer.sub(vec1, vec2)
  • Multiplication: thisLayer.mul(vec, amount)
  • Division: thisLayer.div(vec, amount)

Below are examples of expressions using standard math and updated vector math. The vector math expressions also use the appropriate thisLayer. or thisProperty. prefix when needed.

To find the difference between a wiggle() and the value of a Position property:

// Standard Math:
wiggle() - value;
 
 
// Vector Math:
thisLayer.sub( thisProperty.wiggle(), value );

To interpolate between two values, similar to linear(), but with an extended range beyond the defined minimum and maximum:

// Standard Math:
value1 + ( ( t - tMin ) / ( tMax - tMin ) ) * ( value2 - value1 );
 
 
// Vector Math:
thisLayer.add( value1, thisLayer.mul( thisLayer.div( thisLayer.sub( t, tMin ), thisLayer.sub( tMax, tMin ) ), thisLayer.sub( value2, value1 ) ) );

To loop a Position property in and out:

// Standard Math:
loopIn( "cycle" ) + loopOut( "cycle" ) - value;
 
 
// Vector Math:
thisLayer.sub( thisLayer.add( thisProperty.loopIn( "cycle" ), thisProperty.loopOut( "cycle" ) ), value );

Get help faster and easier

New user?