V8 Runtime Overview

In Apps Script and JavaScript, a runtime or runtime environment contains the JavaScript engine that parses and executes script code. The runtime provides rules for how memory is accessed, how the program can interact with the computer's operating system, and what program syntax is legal. Each web browser has a runtime environment for JavaScript.

Historically, Apps Script has been powered by Mozilla's Rhino JavaScript interpreter. While Rhino provided a convenient way for Apps Script to execute developer scripts, it also tied Apps Script to a specific JavaScript version (ES5). Apps Script developers can't use more modern JavaScript syntax and features in scripts using the Rhino runtime.

To address this concern, Apps Script is now supported by the V8 runtime that powers Chrome and Node.js. You can migrate existing scripts to V8 in order to take advantage of the modern JavaScript syntax and features.

This page describes the new features enabled by V8 and how you can enable V8 for use in your scripts. Migrating scripts to V8 describes steps for migrating existing scripts to use the V8 runtime.

Features of the V8 runtime

Scripts that use the V8 runtime are able to take advantage of the following features:

Modern ECMAScript syntax

You can use modern ECMAScript syntax in scripts that are powered by the V8 runtime. This syntax includes let, const, and many other popular features.

See V8 syntax examples for a short list of popular syntax improvements you can make using the V8 runtime.

Improved function detection

Apps Script function detection is improved for scripts using V8. The new runtime recognizes these function definition formats:

      function normalFunction() {}
      async function asyncFunction() {}
      function* generatorFunction() {}

      var varFunction = function() {}
      let letFunction = function() {}
      const constFunction = function() {}

      var namedVarFunction = function alternateNameVarFunction() {}
      let namedLetFunction = function alternateNameLetFunction() {}
      const namedConstFunction = function alternateNameConstFunction() {}

      var varAsyncFunction = async function() {}
      let letAsyncFunction = async function() {}
      const constAsyncFunction = async function() {}

      var namedVarAsyncFunction = async function alternateNameVarAsyncFunction() {}
      let namedLetAsyncFunction = async function alternateNameLetAsyncFunction() {}
      const namedConstAsyncFunction = async function alternateNameConstAsyncFunction() {}

      var varGeneratorFunction = function*() {}
      let letGeneratorFunction = function*() {}
      const constGeneratorFunction = function*() {}

      var namedVarGeneratorFunction = function* alternateNameVarGeneratorFunction() {}
      let namedLetGeneratorFunction = function* alternateNameLetGeneratorFunction() {}
      const namedConstGeneratorFunction = function* alternateNameConstGeneratorFunction() {}

      var varLambda = () => {}
      let letLambda = () => {}
      const constLambda = () => {}

      var varAsyncLambda = async () => {}
      let letAsyncLambda = async () => {}
      const constAsyncLambda = async () => {}

Call object methods from triggers and callbacks

Scripts using V8 can call object methods and class static methods from places where you could already call library methods. These places include the following:

The following V8 example shows the use of object methods when constructing menu items in Google Sheets:

function onOpen() {
  var ui = SpreadsheetApp.getUi(); // Or DocumentApp, SlidesApp, or FormApp.
  ui.createMenu('Custom Menu')
      .addItem('First item', 'menu.item1')
          .addItem('Second item', 'menu.item2'))

var menu = {
  item1: function() {
    SpreadsheetApp.getUi().alert('You clicked: First item');
  item2: function() {
    SpreadsheetApp.getUi().alert('You clicked: Second item');

UI changes for logging

Apps Script provides two logging services: the Logger service and the console class. Both of these services write logs to the same Stackdriver Logging service.

If your script uses the Rhino runtime, selecting View > Logs in the Apps Script editor only shows you recent logs written by the Logger service. You must select View > Stackdriver Logging to see logs written with the console class.

For scripts using the V8 runtime, the script editor View > Logs menu item shows both Logger and console results for the most recent execution in the current session. You can still find older logs by selecting View > Stackdriver Logging.

UI changes for executions

The location of execution transcripts has changed under V8. If your script uses the Rhino runtime, you can find execution transcripts for scripts selecting the View > Execution Transcript menu in the Apps Script editor. This opens an Execution transcript dialog that lists the most recent execution transcript, which lists calls to Apps Script services along with associated timestamps.

If your script uses the V8 runtime, execution transcripts are no longer available. Instead you can view the execution history in the Apps Script dashboard by selecting View > Executions in the Apps Script editor. This opens the Executions panel for the script project. From here you can select an execution to see Stackdriver logs associated with it. Unlike execution transcripts in Rhino, the Executions panel can show you an execution history from multiple runs of your script (instead of only the most recent execution).

V8 syntax examples

The following is a short list of popular syntactical features available to scripts using the V8 runtime.

let and const

The let and const keywords allow you to define block scope local variables and block scope constants, respectively.

// V8 runtime
let s = "hello";
if (s === "hello") {
  let s = "world";
  console.log(s);  // Prints "world"
console.log(s);  // Prints "hello"

const N = 100;
N = 5; // Results in TypeError

Arrow functions

Arrow functions provide a compact way of defining functions within expressions.

// Rhino runtime
function square(x) {
  return x * x;

console.log(square(5));  // Outputs 25
// V8 runtime
const square = x => x * x;
console.log(square(5));  // Outputs 25

// Outputs [1, 4, 9]
console.log([1, 2, 3].map(x => x * x));


Classes provide a means to conceptually organize code with inheritance. Classes in V8 are primarily syntactical sugar over the JavaScript prototype-based inheritance.

// V8 runtime
class Rectangle {
  constructor(width, height) { // class constructor
    this.width = width;
    this.height = height;

  logToConsole() { // class method
    console.log(`Rectangle(width=${this.width}, height=${this.height})`);

const r = new Rectangle(10, 20);
r.logToConsole();  // Outputs Rectangle(width=10, height=20)

Destructuring assignments

Destructuring assignment expressions are a quick way to unpack values from arrays and objects into distinct variables.

// Rhino runtime
var data = {a: 12, b: false, c: 'blue'};
var a = data.a;
var c = data.c;
console.log(a, c);  // Outputs 12 "blue"

var array = [1, 2, 3];
var x = a[0];
var y = a[1];
var z = a[2];
console.log(x, y, z);  // Outputs 1 2 3
// V8 runtime
var data = {a: 12, b: false, c: 'blue'};
var {a, c} = data;
console.log(a, c);  // Outputs 12 "blue"

var array = [1, 2, 3];
var [x, y, z] = array;
console.log(x, y, z);  // Outputs 1 2 3


Template literals

Template literals are string literals that allow embedded expressions. They let you avoid more complex string concatenation statements.

// Rhino runtime
var name =
  'Hi ' + first + ' ' + last + '.';
var url =
  + id;
// V8 runtime
var name = `Hi ${first} ${last}.`;
var url =


Default parameters

Default parameters let you specify default values for function parameters in the function declaration. This can simplify the code in the function body as it removes the need to explicitly assign default values to missing parameters.

// Rhino runtime
function hello(greeting, name) {
    greeting = greeting || "hello";
    name = name || "world";
        greeting + " " + name + "!");

hello();  // Outputs "hello world!"
// V8 runtime
var hello =
  function(greeting="hello", name="world") {
        greeting + " " + name + "!");

hello();  // Outputs "hello world!"


Multi-line strings

You can define multi-line strings using the same syntax as template literals. As with template literals, this syntax lets you avoid string concatenations and simplify string definitions.

// Rhino runtime
var multiline = "This string is sort of\n"
+ "like a multi-line string,\n"
+ "but it's not really one.";
// V8 runtime
var multiline = `This on the other hand,
actually is a multi-line string,
thanks to JavaScript ES6`;

Enabling the V8 runtime

If a script is using the Rhino runtime, you can switch it to V8 by doing the following:

  1. Open the script in the Apps Script editor.
  2. Select the Run > Enable new Apps Script runtime powered by V8.
  3. Save your script.

Alternatively you can select the script runtime directly by editing the script manifest file:

  1. Open the script in the Apps Script editor.
  2. Select View > Show project manifest.
  3. In the resulting appsscript.json manifest file, set the runtimeVersion field to the value V8.
  4. Save your script.

Migrating scripts to V8 explains other steps you should take to ensure your script functions well using V8.

Enabling the Rhino runtime

If your script is using V8 and you need to switch it to use the original Rhino runtime, do the following:

  1. Open the script in the Apps Script editor.
  2. Select Run > Disable new Apps Script runtime powered by V8.

Alternatively, edit your script manifest and set the runtimeVersion field to DEPRECATED_ES5.

How do I migrate existing scripts?

The Migrating scripts to V8 guide describes the steps you need to take to migrate an existing script to use V8. This involves enabling the V8 runtime and checking the script for any known incompatibilities.

Automatic migration of scripts to V8

Starting February 18, 2020 Google will start gradually migrating existing scripts that pass our automated compatibility test to V8. The affected scripts continue to function normally after migration.

If you want to opt a script out of automatic migration, set the runtimeVersion field in its manifest to DEPRECATED_ES5. You can choose to manually migrate the script to V8 at any time thereafter.

How do I report bugs?

The Support guide explains how to get programming help on Stack Overflow, search existing issue reports, file new bugs, and make new feature requests.