Switch an old script from Rhino to the V8 runtime

Published: (June 12, 2026 at 08:40 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

bulldo.gs

Originally written for bulldo.gs — republished here with the canonical link pointing home.

I want to enable the V8 runtime on an existing Apps Script project so I can use modern JavaScript, but I am worried about breaking things that are already working.

// appsscript.json — set runtimeVersion to enable V8
// Rollback: change V8 back to DEPRECATED_ES5
{
  "timeZone": "America/New_York",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

// Code.gs — safe V8-compatible replacement for a common Rhino pattern
// Rhino allowed: for each (var item in collection) {}
// V8 requires standard for...of instead
function listSheetNames() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var names = [];
  var sheets = ss.getSheets();
  for (var i = 0; i `, and `__iterator__` or `__defineGetter__` on prototypes. Do a text search across all .gs files for those strings before you change runtimeVersion.

The Apps Script editor has no project-wide search, so either use the browser's find-in-page on each file, or copy all your .gs files into a local editor with multi-file search. Any hit needs to be rewritten: `for each` becomes a standard `for...of` or indexed `for` loop; XML literals need to be replaced with `XmlService` calls or plain strings; the prototype methods have no direct replacement and usually need a logic rewrite.

After fixing the files, change `runtimeVersion` to `V8`, save, and immediately run one function manually from the editor toolbar. If the Execution Log shows the function completing, your triggers are also alive. If you see a red syntax error, V8 caught something the search missed — read the error, fix the line, repeat.

  
  
  Instant rollback while you keep fixing files

If production triggers are firing and you need to un-break them immediately, set `"runtimeVersion": "DEPRECATED_ES5"` in appsscript.json and save. Rhino resumes within seconds. You do not need to revert any .gs file changes you already made — DEPRECATED_ES5 tolerates both old and new syntax.

This lets you migrate file by file. Fix one .gs file, flip to V8, test, flip back to DEPRECATED_ES5, fix the next file. Tedious for large projects, but it keeps triggers running throughout. Once every file passes a V8 test run, leave runtimeVersion set to V8 permanently.

One practical note: the `DEPRECATED_ES5` value is exactly that — deprecated. Google has not announced a hard removal date as of mid-2026, but they have signaled V8 is the intended path. Old scripts will keep running on Rhino for now, but new V8-only APIs (like `globalThis` or native `Promise` support in triggers) are not back-ported, so staying on Rhino indefinitely means foregoing those.

  
  
  FAQ

**After I set runtimeVersion to V8, all my triggers stopped running with no error in the dashboard. What happened?**

A parse-time error in any .gs file silently kills initialization. Open the editor, run any function manually, and look at the Execution Log — it will show the actual syntax error and the file name. Fix that line, then triggers resume automatically without redeployment.

**Can I use arrow functions and const/let after switching to V8?**

Yes. V8 supports ES2019 and most ES2020 syntax: arrow functions, const/let, destructuring, spread, async/await, optional chaining, and nullish coalescing. The one thing that does not work the same way is top-level await — Apps Script still requires async functions to be called from a synchronous trigger wrapper.

**My script uses XmlService and it works fine on Rhino. Will it break on V8?**

XmlService itself is a Google service and is runtime-agnostic — it works on both. What breaks under V8 is E4X, the old Rhino XML literal syntax (angle-bracket XML directly in JavaScript code). If your script uses XmlService.parse() and XmlService.getContentType() style calls rather than inline XML literals, it will migrate without changes.

**Is there a way to see which runtime a deployed script is currently using without opening the manifest?**

Not from outside the editor. You have to open the project, enable manifest display in Project Settings, and read appsscript.json. The Apps Script API (the REST API for managing scripts) does expose the runtimeVersion field in the project Content resource if you need to audit it programmatically across many projects.

*Want the plain-English version? Describe the automation at [bulldo.gs](https://bulldo.gs/switch-from-rhino-to-v8-runtime-apps-script) and get working Apps Script back — free, no login.*
0 views
Back to Blog

Related posts

Read more »

The spec is in the wrong place

My day job is at a large tech company. Hundreds of engineering teams, and every one of them is somewhere different on AI adoption. Some are still treating codin...

The Heuristics Say Don't

A culture that only records its disasters ends up with a biased archive. Wars documented, plagues chronicled, collapses catalogued. The quiet decades go unwritt...