Apps Script V8 Runtime Limitations
Google Apps Script is a cloud-based scripting platform that lets you automate tasks, customize functions, and build solutions within Google Workspace using JavaScript and the V8 runtime. V8 is the JavaScript engine that powers Google Chrome and Node.js. However, the runtime has some limitations that you should be aware of when developing Apps Script projects and not all JavaScript functions and interfaces are supported.
WinterCG Minimum Common Web Platform API
This is similar to the challenges being addressed by the Web-interoperable Runtimes Community Group (WinterCG) project, which aims to improve API interoperability across different JavaScript runtimes. The WinterCG has a draft Minimum Common Web Platform API proposal that aims to define a minimum set of APIs that should be available in all JavaScript runtimes. I took this draft and tested the APIs in the Apps Script V8 runtime to see which ones are supported and which ones are not. Below are the results generated by the script:
JavaScript APIs and availability in Apps Script V8
| JavaScript API | Available | Error |
|---|---|---|
| AbortController | ❌ | AbortController is not defined |
| AbortSignal | ❌ | AbortSignal is not defined |
| atob | ❌ | atob is not defined |
| Blob | ❌ | Blob is not defined |
| btoa | ❌ | btoa is not defined |
| ByteLengthQueuingStrategy | ❌ | ByteLengthQueuingStrategy is not defined |
| clearInterval | ❌ | clearInterval is not defined |
| clearTimeout | ❌ | clearTimeout is not defined |
| CompressionStream | ❌ | CompressionStream is not defined |
| console | ✅ | - |
| CountQueuingStrategy | ❌ | CountQueuingStrategy is not defined |
| crypto | ❌ | crypto is not defined |
| Crypto | ❌ | Crypto is not defined |
| CryptoKey | ❌ | CryptoKey is not defined |
| DecompressionStream | ❌ | DecompressionStream is not defined |
| DOMException | ❌ | DOMException is not defined |
| Event | ❌ | Event is not defined |
| EventTarget | ❌ | EventTarget is not defined |
| fetch | ❌ | fetch is not defined |
| File | ❌ | File is not defined |
| FormData | ❌ | FormData is not defined |
| Headers | ❌ | Headers is not defined |
| navigator.userAgent | ❌ | navigator is not defined |
| performance.now | ❌ | performance is not defined |
| performance.timeOrigin | ❌ | performance is not defined |
| queueMicrotask | ❌ | queueMicrotask is not defined |
| ReadableByteStreamController | ❌ | ReadableByteStreamController is not defined |
| ReadableStream | ❌ | ReadableStream is not defined |
| ReadableStreamBYOBReader | ❌ | ReadableStreamBYOBReader is not defined |
| ReadableStreamBYOBRequest | ❌ | ReadableStreamBYOBRequest is not defined |
| ReadableStreamDefaultController | ❌ | ReadableStreamDefaultController is not defined |
| ReadableStreamDefaultReader | ❌ | ReadableStreamDefaultReader is not defined |
| Request | ❌ | Request is not defined |
| Response | ❌ | Response is not defined |
| setInterval | ❌ | setInterval is not defined |
| setTimeout | ❌ | setTimeout is not defined |
| structuredClone | ❌ | structuredClone is not defined |
| SubtleCrypto | ❌ | SubtleCrypto is not defined |
| TextDecoder | ❌ | TextDecoder is not defined |
| TextDecoderStream | ❌ | TextDecoderStream is not defined |
| TextEncoder | ❌ | TextEncoder is not defined |
| TextEncoderStream | ❌ | TextEncoderStream is not defined |
| TransformStream | ❌ | TransformStream is not defined |
| TransformStreamDefaultController | ❌ | TransformStreamDefaultController is not defined |
| URL | ❌ | URL is not defined |
| URLSearchParams | ❌ | URLSearchParams is not defined |
| WebAssembly.compile | ✅ | - |
| WebAssembly.compileStreaming | ❌ | WebAssembly.compileStreaming is not a function |
| WebAssembly.Global | ✅ | - |
| WebAssembly.Instance | ✅ | - |
| WebAssembly.instantiate | ✅ | - |
| WebAssembly.instantiateStreaming | ❌ | WebAssembly.instantiateStreaming is not a function |
| WebAssembly.Memory | ✅ | - |
| WebAssembly.Module | ✅ | - |
| WebAssembly.Table | ✅ | - |
| WebAssembly.validate | ✅ | - |
| WritableStream | ❌ | WritableStream is not defined |
| WritableStreamDefaultController | ❌ | WritableStreamDefaultController is not defined |
Runtime workarounds
For some APIs there is an Apps Script specific alternative. For example, the fetch API is not available in Apps Script, but you can use the UrlFetchApp service instead.
// fetch('https://api.example.com/data')
UrlFetchApp.fetch("https://api.example.com/data"); Other examples such as setTimeout and setInterval are not available in Apps Script, but you can use the Utilities.sleep method.
// setTimeout(() => console.log('Hello'), 1000)
Utilities.sleep(1000);
console.log("Hello"); It is also possible to use polyfills or workarounds to achieve the same functionality. An example of this is the TextEncoder and TextDecoder interfaces, which are not available in Apps Script, but you can use the util NPM package to achieve the same functionality with some manual setup or bundling outside of Apps Script.
One thing to keep in mind is that streaming functionality is not available in Apps Script and there really isn’t a good workaround for this. However, there is asynchronous support which is needed for the WebAssembly interface!
© 2024 by Justin Poehnelt is licensed under CC BY-SA 4.0