ב-Google Apps Script וב-JavaScript, זמן ריצה או סביבת זמן ריצה כוללים את מנוע ה-JavaScript שמנתח ומריץ קוד סקריפט. סביבת זמן הריצה מספקת כללים לגבי הגישה לזיכרון, האינטראקציה של התוכנית עם מערכת ההפעלה של המחשב והתחביר החוקי של התוכנית. לכל דפדפן אינטרנט יש סביבת זמן ריצה ל-JavaScript.
בעבר, Apps Script הופעל על ידי Rhino, מתורגמן JavaScript של Mozilla. בעוד ש-Rhino סיפק דרך נוחה ל-Apps Script להריץ סקריפטים של מפתחים, הוא גם קשר את Apps Script לגרסה ספציפית של JavaScript (ES5). מפתחים של Apps Script לא יכולים להשתמש בתחביר ובמאפיינים מודרניים יותר של JavaScript בסקריפטים שמשתמשים בסביבת זמן הריצה של Rhino.
כדי לפתור את הבעיה הזו, Apps Script נתמך עכשיו על ידי זמן הריצה V8 שמפעיל את Chrome ו-Node.js. העברת סקריפטים קיימים ל-V8 כדי ליהנות מהתחביר והתכונות המתקדמים של JavaScript.
בדף הזה מוסבר על התכונות החדשות שמופעלות על ידי V8 ואיך אפשר להפעיל את V8 לשימוש בסקריפטים. במאמר העברת סקריפטים ל-V8 מפורטים השלבים להעברת סקריפטים קיימים לשימוש בסביבת זמן הריצה של V8.
תכונות של סביבת זמן הריצה V8
סקריפטים שמשתמשים בסביבת ההרצה של V8 יכולים ליהנות מהתכונות הבאות:
תחביר ECMAScript מודרני
שימוש בתחביר מודרני של ECMAScript בסקריפטים שמופעלים על ידי סביבת ההרצה של V8. התחביר הזה כולל את let, את const ועוד הרבה תכונות פופולריות.
במאמר דוגמאות לתחביר V8 מופיעה רשימה קצרה של שיפורים פופולריים בתחביר שאפשר לבצע באמצעות סביבת ההרצה של V8.
לסביבת זמן הריצה V8 של Apps Script יש כמה מגבלות והבדלים משמעותיים בהשוואה לסביבות זמן ריצה נפוצות אחרות של JavaScript. פרטים נוספים זמינים במאמר בנושא מגבלות של זמן הריצה של Apps Script V8.
זיהוי משופר של פונקציות
הזיהוי של פונקציות Apps Script משופר בסקריפטים שמשתמשים ב-V8. סביבת זמן הריצה החדשה מזהה את הפורמטים הבאים של הגדרות פונקציות:
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 מטריגרים ומקריאות חוזרות
סקריפטים שמשתמשים ב-V8 יכולים להפעיל שיטות של אובייקטים ושיטות סטטיות של מחלקות ממקומות שבהם כבר הייתה לכם אפשרות להפעיל שיטות של ספריות. המקומות האלה כוללים:
- טריגרים של מניפסט בתוספים ל-Google Workspace
- טריגרים שניתן להתקין
- פריטים בתפריט בכלי העריכה של Google Workspace
- פונקציות קריאה חוזרת של המשתמש, כמו זו שמתוארת ב
ScriptApp.newStateToken()דוגמת הקוד.
בדוגמה הבאה של V8 אפשר לראות איך משתמשים בשיטות של אובייקטים כשיוצרים פריטים בתפריט ב-Google Sheets:
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');
}
}
צפייה ביומנים
ב-Apps Script יש שני שירותי רישום ביומן: השירות Logger והסיווג console. שני השירותים האלה כותבים יומנים לאותו שירות Stackdriver Logging.
כדי להציג את היומנים Logger ו-console, בחלק העליון של הכלי לעריכת סקריפטים לוחצים על יומן הרצה.
הצגת הביצועים
כדי לראות את היסטוריית ההרצה של הסקריפט, פותחים את פרויקט Apps Script ובצד ימין לוחצים על הפעלות .
בחלונית Executions לא מוצגים יומנים עם חותמות זמן של כל קריאות השירות של Apps Script. משתמשים בשירות console כדי ליצור הודעות יומן מתאימות. כל היומנים שנוצרו באמצעות console מופיעים בחלונית Executions.
דוגמאות לתחביר V8
בהמשך מופיעה רשימה קצרה של תכונות תחביריות פופולריות שזמינות לסקריפטים באמצעות סביבת ההרצה של V8.
let וגם const
מילות המפתח let ו-const מאפשרות להגדיר משתנים מקומיים בהיקף של בלוק וקבועים בהיקף של בלוק, בהתאמה.
// 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 |
פונקציות חץ
פונקציות חץ מספקות דרך קומפקטית להגדרת פונקציות בתוך ביטויים.
// 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 מספקות דרך לארגן קוד באופן קונספטואלי באמצעות ירושה. מחלקות ב-V8 הן בעיקר תחביר נוח לשימוש בירושה מבוססת-אב-טיפוס של 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) |
השמה באמצעות פירוק מבנה
ביטויי השמה של פירוק מאפשרים לפרוק במהירות ערכים ממערכים ומאובייקטים למשתנים נפרדים.
// 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 |
תבניות מילוליות
תבניות מילוליות הן מחרוזות מילוליות שמאפשרות הבעות מוטמעות. הם מאפשרים לכם להימנע מהצהרות מורכבות יותר של שרשור מחרוזות.
// 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}`; |
פרמטרים שמוגדרים כברירת מחדל
פרמטרים של ברירת מחדל מאפשרים לכם לציין ערכי ברירת מחדל לפרמטרים של פונקציה בהצהרה על הפונקציה. השימוש בערכי ברירת מחדל יכול לפשט את הקוד בגוף הפונקציה, כי הוא מבטל את הצורך להקצות ערכי ברירת מחדל לפרמטרים חסרים באופן מפורש.
// 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!" |
מחרוזות מרובות שורות
מגדירים מחרוזות מרובות שורות באמצעות אותו תחביר כמו תבניות מילוליות. בדומה לשימוש במחרוזות תבנית, התחביר הזה מאפשר לכם להימנע משרשור מחרוזות ולפשט את הגדרות המחרוזות.
// 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`; |
מגבלות של סביבת ההרצה V8
סביבת זמן הריצה של Apps Script V8 היא לא סביבת Node.js או דפדפן סטנדרטית. הדבר עלול לגרום לבעיות תאימות כשקוראים לספריות של צד שלישי או כשמתאימים דוגמאות קוד מסביבות JavaScript אחרות.
ממשקי API לא זמינים
ממשקי ה-API הרגילים הבאים של JavaScript לא זמינים בזמן הריצה של V8 ב-Apps Script:
- טיימרים:
setTimeout,setInterval,clearTimeout,clearInterval - Streams:
ReadableStream,WritableStream,TextEncoder,TextDecoder - Web APIs:
fetch,FormData,File,Blob,URL,URLSearchParams,DOMException,atob,btoa - מטבעות קריפטו:
crypto,SubtleCrypto - אובייקטים גלובליים:
window, navigator, performance, process(Node.js)
אפשר להשתמש בממשקי Apps Script API הבאים כחלופות:
- טיימרים: משתמשים ב-
Utilities.sleepלהשהיות סינכרוניות. אין תמיכה בטיימרים אסינכרוניים. - Fetch: אפשר להשתמש ב-
UrlFetchApp.fetch(url, params)כדי לשלוח בקשות HTTP(S). - atob: משתמשים ב-
Utilities.base64Decodeכדי לפענח מחרוזות בקידוד Base64. - btoa: משתמשים ב-
Utilities.base64Encodeכדי לקודד מחרוזות ב-Base64. - Crypto: משתמשים ב-
Utilitiesלפונקציות קריפטוגרפיות כמוcomputeDigest,computeHmacSha256Signature, ו-computeRsaSha256Signature.
בממשקי API שאין להם חלופה ב-Apps Script, כמו TextEncoder, אפשר לפעמים להשתמש ב-polyfill. Polyfill היא ספריה שמשכפלת פונקציונליות של API שלא זמינה כברירת מחדל בסביבת זמן הריצה.
לפני שמשתמשים ב-polyfill, צריך לוודא שהוא תואם לסביבת זמן הריצה V8 של Apps Script.
מגבלות אסינכרוניות
זמן הריצה של V8 תומך בתחביר async ו-await ובאובייקט Promise.
עם זאת, סביבת זמן הריצה של Apps Script היא סינכרונית באופן מהותי.
- משימות קטנות (נתמכות): סביבת זמן הריצה מעבדת את תור המשימות הקטנות (שבו מתבצעות קריאות חוזרות של
Promise.thenופתרונות שלawait) אחרי שסטאק הביצוע הנוכחי מתרוקן. - משימות מאקרו (לא נתמכות): ב-Apps Script אין לולאת אירועים רגילה למשימות מאקרו. פונקציות כמו
setTimeoutו-setIntervalלא זמינות. - WebAssembly Exception: ה-WebAssembly API הוא התכונה המובנית היחידה שפועלת באופן לא חוסם בסביבת זמן הריצה, ומאפשרת דפוסי קומפילציה אסינכרוניים ספציפיים (WebAssembly.instantiate).
כל פעולות הקלט/פלט (I/O), כמו UrlFetchApp.fetch, הן פעולות חסימה. כדי להשיג בקשות רשת מקבילות, משתמשים ב-UrlFetchApp.fetchAll.
מגבלות על כיתות
לסביבת זמן הריצה V8 יש מגבלות ספציפיות לגבי תכונות מודרניות של מחלקות ES6+:
- שדות פרטיים: שדות פרטיים של מחלקה (לדוגמה,
#field) לא נתמכים וגורמים לשגיאות בניתוח. כדאי להשתמש בסגירות או ב-WeakMapכדי להשיג אנקפסולציה אמיתית. - שדות סטטיים: לא ניתן להשתמש בהצהרות ישירות על שדות סטטיים בגוף המחלקה (לדוגמה,
static count = 0;). מקצים מאפיינים סטטיים לכיתה אחרי ההגדרה שלה (לדוגמה,MyClass.count = 0;).
מגבלות המודול
- מודולים של ES6: סביבת ההרצה של V8 לא תומכת במודולים של ES6 (
import/export). כדי להשתמש בספריות, צריך להשתמש ב מנגנון הספריות של Apps Script או לארוז את הקוד ואת התלות שלו בקובץ סקריפט יחיד. (Issue Tracker) - סדר ההרצה של הקבצים: כל קובצי הסקריפט בפרויקט מורצים בהיקף גלובלי. מומלץ להימנע מקוד ברמה העליונה עם תופעות לוואי, ולוודא שפונקציות ומחלקות מוגדרות לפני שמשתמשים בהן בקבצים. אם יש יחסי תלות בין הקבצים, צריך לסדר אותם באופן מפורש בעורך.
הפעלת סביבת זמן הריצה V8
אם סקריפט משתמש בסביבת זמן הריצה של Rhino, צריך להעביר אותו ל-V8. לשם כך:
- פותחים את פרויקט Apps Script.
- בצד ימין, לוחצים על הגדרות הפרויקט .
- מסמנים את תיבת הסימון הפעלה של סביבת זמן הריצה של Chrome V8.
אפשר גם לציין את זמן הריצה של הסקריפט ישירות על ידי עריכת קובץ מניפסט הסקריפט:
- פותחים את פרויקט Apps Script.
- בצד ימין, לוחצים על הגדרות הפרויקט .
- מסמנים את התיבה הצגת קובץ המניפסט 'appsscript.json' בעורך.
- בצד ימין, לוחצים על עריכה >
appsscript.json. - בקובץ המניפסט
appsscript.json, מגדירים את השדהruntimeVersionלערךV8. - למעלה, לוחצים על שמירת הפרויקט .
במאמר העברת סקריפטים ל-V8 מוסבר על שלבים נוספים שצריך לבצע כדי לוודא שהסקריפט יפעל בצורה תקינה באמצעות V8.
הפעלת זמן הריצה של Rhino
אם הסקריפט שלכם משתמש ב-V8 ואתם רוצים להעביר אותו לשימוש בסביבת זמן הריצה המקורית של Rhino, אתם צריכים לעשות את הפעולות הבאות:
- פותחים את פרויקט Apps Script.
- בצד ימין, לוחצים על הגדרות הפרויקט .
- מבטלים את הסימון בתיבת הסימון הפעלת זמן הריצה של Chrome V8.
אפשר גם לערוך את קובץ המניפסט של הסקריפט:
- פותחים את פרויקט Apps Script.
- בצד ימין, לוחצים על הגדרות הפרויקט .
- מסמנים את התיבה הצגת קובץ המניפסט 'appsscript.json' בעורך.
- בצד ימין, לוחצים על עריכה >
appsscript.json. - בקובץ המניפסט
appsscript.json, מגדירים את השדהruntimeVersionלערךDEPRECATED_ES5. - למעלה, לוחצים על שמירת הפרויקט .
איך מעבירים סקריפטים קיימים?
במדריך העברת סקריפטים ל-V8 מפורטים השלבים שצריך לבצע כדי להעביר סקריפט קיים לשימוש ב-V8. התהליך כולל הפעלה של זמן הריצה V8 ובדיקה של הסקריפט כדי לוודא שאין בו בעיות תאימות ידועות.
העברה אוטומטית של סקריפטים ל-V8
החל מ-18 בפברואר 2020, Google תבצע בהדרגה מיגרציה של סקריפטים קיימים שעוברים את בדיקת התאימות האוטומטית שלנו ל-V8. הסקריפטים המושפעים ממשיכים לפעול כרגיל אחרי ההעברה.
אם רוצים להחריג סקריפט מההעברה האוטומטית, צריך להגדיר את השדה
runtimeVersion
במניפסט שלו לערך DEPRECATED_ES5. בכל שלב לאחר מכן, אפשר להעביר את הסקריפט ל-V8 באופן ידני.
איך מדווחים על באגים?
במדריך התמיכה מוסבר איך לקבל עזרה בתכנות ב-Stack Overflow, איך לחפש דוחות בעיות קיימים, איך לדווח על באגים חדשים ואיך לשלוח בקשות לתכונות חדשות.