Omówienie środowiska wykonawczego V8

W Google Apps Script i JavaScript środowisko wykonawcze lub środowisko wykonawcze zawiera silnik JavaScript, który analizuje i wykonuje kod skryptu. Środowisko wykonawcze określa zasady dostępu do pamięci, sposób interakcji programu z systemem operacyjnym komputera oraz prawidłową składnię programu. Każda przeglądarka internetowa ma środowisko wykonawcze dla JavaScriptu.

W przeszłości Apps Script korzystał z interpretera JavaScript Rhino firmy Mozilla. Rhino zapewniało wygodny sposób wykonywania skryptów deweloperskich w Apps Script, ale jednocześnie wiązało Apps Script z określoną wersją JavaScriptu (ES5). Deweloperzy Apps Script nie mogą używać w skryptach nowoczesnej składni i funkcji JavaScriptu, jeśli korzystają ze środowiska wykonawczego Rhino.

Aby rozwiązać ten problem, Apps Script jest teraz obsługiwany przez środowisko wykonawcze V8, które jest używane w Chrome i Node.js. Przenieś istniejące skrypty do V8, aby korzystać z nowoczesnej składni i funkcji JavaScript.

Z tego artykułu dowiesz się, jakie nowe funkcje są dostępne dzięki V8 i jak włączyć V8 w skryptach. Przenoszenie skryptów do V8 opisuje czynności, które należy wykonać, aby przenieść istniejące skrypty do środowiska wykonawczego V8.

Funkcje środowiska wykonawczego V8

Skrypty korzystające ze środowiska wykonawczego V8 mogą korzystać z tych funkcji:

Nowoczesna składnia ECMAScript

Używaj nowoczesnej składni ECMAScript w skryptach, które są obsługiwane przez środowisko wykonawcze V8. Ta składnia obejmuje let, const i wiele innych popularnych funkcji.

Krótką listę popularnych ulepszeń składni, które możesz wprowadzić za pomocą środowiska wykonawczego V8, znajdziesz w przykładach składni V8.

Środowisko wykonawcze Apps Script V8 ma pewne ograniczenia i kluczowe różnice w porównaniu z innymi popularnymi środowiskami wykonawczymi JavaScriptu. Więcej informacji znajdziesz w sekcji Ograniczenia środowiska wykonawczego Apps Script V8.

Ulepszone wykrywanie funkcji

Wykrywanie funkcji Apps Script zostało ulepszone w przypadku skryptów korzystających z V8. Nowe środowisko wykonawcze rozpoznaje te formaty definicji funkcji:

      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 () => {}

Wywoływanie metod obiektów połączeń z poziomu wyzwalaczy i wywołań zwrotnych

Skrypty korzystające z V8 mogą wywoływać metody obiektów i statyczne metody klas w miejscach, w których można było już wywoływać metody biblioteki. Są to między innymi:

Ten przykład w V8 pokazuje użycie metod obiektu podczas tworzenia elementów menu w Arkuszach Google:

function onOpen() {
  const ui = SpreadsheetApp.getUi(); // Or DocumentApp, SlidesApp, or FormApp.
  ui.createMenu('Custom Menu')
      .addItem('First item', 'menu.item1')
      .addSeparator()
      .addSubMenu(ui.createMenu('Sub-menu')
          .addItem('Second item', 'menu.item2'))
      .addToUi();
}

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

Wyświetl logi

Apps Script udostępnia 2 usługi rejestrowania: Logger i klasę console. Obie te usługi zapisują logi w tej samej usłudze Stackdriver Logging.

Aby wyświetlić dzienniki Loggerconsole, u góry edytora skryptów kliknij Dziennik wykonywania.

Wyświetlanie wykonań

Aby wyświetlić historię wykonywania skryptu, otwórz projekt Apps Script i po lewej stronie kliknij Wykonania .

Panel Wykonania nie zawiera logów z sygnaturami czasowymi poszczególnych wywołań usługi Apps Script. Użyj usługi console, aby tworzyć odpowiednie komunikaty dziennika. Wszystkie logi utworzone za pomocą console są wyświetlane w panelu Wykonania.

Przykłady składni V8

Poniżej znajduje się krótka lista popularnych funkcji składniowych dostępnych w skryptach korzystających ze środowiska wykonawczego V8.

letconst

Słowa kluczowe let i const umożliwiają odpowiednio definiowanie zmiennych lokalnych o zakresie bloku i stałych o zakresie bloku.

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

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

Funkcje strzałkowe

Funkcje strzałkowe umożliwiają zwięzłe definiowanie funkcji w wyrażeniach.

// 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));
      

Zajęcia

Klasy umożliwiają koncepcyjne porządkowanie kodu za pomocą dziedziczenia. Klasy w V8 są przede wszystkim cukrem syntaktycznym w stosunku do dziedziczenia opartego na prototypach JavaScript.

// 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)
      

Przypisania destrukcyjne

Wyrażenia przypisania destrukcyjnego to szybki sposób na rozpakowanie wartości z tablic i obiektów do odrębnych zmiennych.

// 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 a = [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
const data = {a: 12, b: false, c: 'blue'};
const {a, c} = data;
console.log(a, c);  // Outputs 12 "blue"


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


      

Literały szablonu

Literały szablonu to literały ciągów znaków, które umożliwiają umieszczanie wyrażeń. Pozwalają one uniknąć bardziej złożonych instrukcji łączenia ciągów znaków.

// Rhino runtime
var name =
  'Hi ' + first + ' ' + last + '.';
var url =
  'http://localhost:3000/api/messages/'
  + id;
      
// V8 runtime
const name = `Hi ${first} ${last}.`;
const url =
  `http://localhost:3000/api/messages/${id}`;


      

Parametry domyślne

Parametry domyślne umożliwiają określanie wartości domyślnych parametrów funkcji w deklaracji funkcji. Może to uprościć kod w treści funkcji, ponieważ eliminuje konieczność jawnego przypisywania wartości domyślnych do brakujących parametrów.

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

hello();  // Outputs "hello world!"
      
// V8 runtime
const hello =
  function(greeting="hello", name="world") {
      console.log(
        greeting + " " + name + "!");
  }

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

      

Ciągi wielowierszowe

Definiuj ciągi wielowierszowe, używając tej samej składni co literały szablonu. Podobnie jak w przypadku literałów szablonu ta składnia pozwala uniknąć łączenia ciągów znaków i uprościć definicje ciągów znaków.

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

Ograniczenia środowiska wykonawczego V8

Środowisko wykonawcze V8 Apps Script nie jest standardowym środowiskiem Node.js ani przeglądarki. Może to powodować problemy ze zgodnością podczas wywoływania bibliotek innych firm lub dostosowywania przykładów kodu z innych środowisk JavaScript.

Niedostępne interfejsy API

Te standardowe interfejsy JavaScript API NIE są dostępne w środowisku wykonawczym V8 Apps Script:

  • Liczniki czasu: setTimeout, setInterval, clearTimeout, clearInterval
  • Strumienie: ReadableStream, WritableStream, TextEncoder, TextDecoder
  • Interfejsy API sieci: fetch, FormData, File, Blob, URL, URLSearchParams, DOMException, atob, btoa
  • Kryptowaluty: crypto, SubtleCrypto
  • Obiekty globalne: window, navigator, performance, process (Node.js)

Zamiast tego używaj tych interfejsów Apps Script API:

W przypadku interfejsów API, które nie mają alternatywy w Apps Script, np. TextEncoder, możesz czasami użyć polyfill. Polyfill to biblioteka, która replikuje funkcje interfejsu API niedostępne domyślnie w środowisku wykonawczym. Zanim użyjesz polyfillu, upewnij się, że jest on zgodny ze środowiskiem wykonawczym V8 w Apps Script.

Ograniczenia asynchroniczne

Środowisko wykonawcze V8 obsługuje składnię asyncawait oraz obiekt Promise. Środowisko wykonawcze Apps Script jest jednak zasadniczo synchroniczne.

  • Mikrozadania (obsługiwane): środowisko wykonawcze przetwarza kolejkę mikrozadań (w której występują wywołania zwrotne Promise.then i rozwiązania await) po wyczyszczeniu bieżącego stosu wywołań.
  • Makrozadania (nieobsługiwane): Apps Script nie ma standardowej pętli zdarzeń dla makrozadań. Funkcje takie jak setTimeoutsetInterval są niedostępne.
  • Wyjątek dotyczący WebAssembly: interfejs WebAssembly API jest jedyną wbudowaną funkcją, która działa w sposób nieblokujący w środowisku wykonawczym, co umożliwia stosowanie określonych asynchronicznych wzorców kompilacji (WebAssembly.instantiate).

Wszystkie operacje wejścia/wyjścia, takie jak UrlFetchApp.fetch, są blokujące. Aby uzyskać równoległe żądania sieciowe, użyj UrlFetchApp.fetchAll.

Ograniczenia dotyczące zajęć

Środowisko wykonawcze V8 ma określone ograniczenia dotyczące nowoczesnych funkcji klas ES6+:

  • Pola prywatne: prywatne pola klasy (np. #field) nie są obsługiwane i powodują błędy analizowania. Aby uzyskać prawdziwe hermetyzowanie, rozważ użycie domknięć lub WeakMap.
  • Pola statyczne: bezpośrednie deklaracje pól statycznych w treści klasy (np. static count = 0;) nie są obsługiwane. Przypisz do klasy właściwości statyczne po jej zdefiniowaniu (np. MyClass.count = 0;).

Ograniczenia modułów

  • Moduły ES6: środowisko wykonawcze V8 nie obsługuje modułów ES6 (import / export). Aby używać bibliotek, musisz skorzystać z mechanizmu bibliotek Apps Script lub połączyć kod i jego zależności w jeden plik skryptu. (Issue Tracker)
  • Kolejność wykonywania plików: wszystkie pliki skryptu w projekcie są wykonywane w zakresie globalnym. Najlepiej unikać kodu najwyższego poziomu z efektami ubocznymi i upewnić się, że funkcje i klasy są zdefiniowane przed użyciem w plikach. W edytorze możesz jawnie uporządkować pliki, jeśli istnieją między nimi zależności.

Włącz środowisko wykonawcze V8

Jeśli skrypt korzysta ze środowiska wykonawczego Rhino, przełącz go na V8, wykonując te czynności:

  1. Otwórz projekt Apps Script.
  2. Po lewej stronie kliknij Ustawienia projektu .
  3. Zaznacz pole wyboru Włącz środowisko wykonawcze Chrome V8.

Możesz też określić środowisko wykonawcze skryptu bezpośrednio, edytując plik manifestu skryptu:

  1. Otwórz projekt Apps Script.
  2. Po lewej stronie kliknij Ustawienia projektu .
  3. Zaznacz pole wyboru Wyświetlaj plik manifestu „appsscript.json” w edytorze.
  4. Po lewej stronie kliknij Edytor > appsscript.json.
  5. W pliku manifestu appsscript.json ustaw pole runtimeVersion na wartość V8.
  6. U góry kliknij Zapisz projekt .

W artykule Przenoszenie skryptów do V8 znajdziesz inne czynności, które należy wykonać, aby skrypt działał prawidłowo w środowisku V8.

Włącz środowisko wykonawcze Rhino

Jeśli Twój skrypt korzysta z V8 i musisz przełączyć go na oryginalne środowisko wykonawcze Rhino, wykonaj te czynności:

  1. Otwórz projekt Apps Script.
  2. Po lewej stronie kliknij Ustawienia projektu .
  3. Odznacz pole wyboru Włącz środowisko wykonawcze Chrome 8.

Możesz też edytować plik manifestu skryptu:

  1. Otwórz projekt Apps Script.
  2. Po lewej stronie kliknij Ustawienia projektu .
  3. Zaznacz pole wyboru Wyświetlaj plik manifestu „appsscript.json” w edytorze.
  4. Po lewej stronie kliknij Edytor > appsscript.json.
  5. W pliku manifestu appsscript.json ustaw pole runtimeVersion na wartość DEPRECATED_ES5.
  6. U góry kliknij Zapisz projekt .

Jak przeprowadzić migrację istniejących skryptów?

W przewodniku Przenoszenie skryptów do V8 znajdziesz opis czynności, które musisz wykonać, aby przenieść istniejący skrypt do środowiska V8. Obejmuje to włączenie środowiska wykonawczego V8 i sprawdzenie skryptu pod kątem znanych niezgodności.

Automatyczna migracja skryptów do V8

Od 18 lutego 2020 roku Google stopniowo przenosi do V8 dotychczasowe skrypty, które przejdą nasz automatyczny test zgodności. Po migracji skrypty, których dotyczy problem, będą nadal działać normalnie.

Jeśli chcesz zrezygnować z automatycznej migracji skryptu, ustaw w jego manifeście pole runtimeVersion na wartość DEPRECATED_ES5. W dowolnym momencie możesz ręcznie przenieść skrypt do V8.

Jak zgłaszać błędy?

przewodniku pomocy znajdziesz informacje o tym, jak uzyskać pomoc dotyczącą programowania na stronie Stack Overflow, wyszukiwać istniejące raporty o problemach, zgłaszać nowe błędy i przesyłać prośby o nowe funkcje.