V8 रनटाइम की खास जानकारी

Apps Script और JavaScript में, रनटाइम या रनटाइम एनवायरमेंट में JavaScript इंजन होता है. यह इंजन, स्क्रिप्ट कोड को पार्स करता है और उसे लागू करता है. रनटाइम, मेमोरी को ऐक्सेस करने के तरीके के बारे में नियम तय करता है. साथ ही, यह भी तय करता है कि प्रोग्राम, कंप्यूटर के ऑपरेटिंग सिस्टम के साथ कैसे इंटरैक्ट कर सकता है और प्रोग्राम का कौनसा सिंटैक्स मान्य है. हर वेब ब्राउज़र में, JavaScript के लिए रनटाइम एनवायरमेंट होता है.

पहले, Apps Script को Mozilla के Rhino JavaScript इंटरप्रेटर से चलाया जाता था. Rhino, Apps Script को डेवलपर स्क्रिप्ट लागू करने का आसान तरीका उपलब्ध कराता है. हालांकि, यह Apps Script को JavaScript के किसी खास वर्शन (ES5) से भी जोड़ता है. Apps Script डेवलपर, Rhino रनटाइम का इस्तेमाल करने वाली स्क्रिप्ट में JavaScript के ज़्यादा नए सिंटैक्स और सुविधाओं का इस्तेमाल नहीं कर सकते.

इस समस्या को हल करने के लिए, Apps Script अब V8 रनटाइम के साथ काम करता है. यह रनटाइम Chrome और Node.js को बेहतर बनाता है. मॉडर्न JavaScript सिंटैक्स और सुविधाओं का फ़ायदा पाने के लिए, मौजूदा स्क्रिप्ट को V8 पर माइग्रेट किया जा सकता है.

इस पेज पर, V8 की मदद से चालू की गई नई सुविधाओं के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि अपनी स्क्रिप्ट में V8 का इस्तेमाल करने के लिए, इसे कैसे चालू किया जा सकता है. V8 पर स्क्रिप्ट माइग्रेट करना लेख में, मौजूदा स्क्रिप्ट को V8 रनटाइम का इस्तेमाल करने के लिए माइग्रेट करने का तरीका बताया गया है.

V8 रनटाइम की सुविधाएं

V8 रनटाइम का इस्तेमाल करने वाली स्क्रिप्ट, इन सुविधाओं का फ़ायदा ले सकती हैं:

ECMAScript का नया सिंटैक्स

V8 रनटाइम की मदद से चलने वाली स्क्रिप्ट में, आधुनिक ECMAScript सिंटैक्स का इस्तेमाल किया जा सकता है. इस सिंटैक्स में let, const, और कई अन्य लोकप्रिय सुविधाएं शामिल हैं.

V8 रनटाइम का इस्तेमाल करके, सिंटैक्स में किए जा सकने वाले लोकप्रिय सुधारों की छोटी सूची के लिए, V8 सिंटैक्स के उदाहरण देखें.

फ़ंक्शन का पता लगाने की बेहतर सुविधा

V8 का इस्तेमाल करने वाली स्क्रिप्ट के लिए, Apps Script फ़ंक्शन का पता लगाने की सुविधा को बेहतर बनाया गया है. नया रनटाइम, फ़ंक्शन की परिभाषा के इन फ़ॉर्मैट को पहचानता है:

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

ट्रिगर और कॉलबैक से कॉल ऑब्जेक्ट के तरीकों को कॉल करना

V8 का इस्तेमाल करने वाली स्क्रिप्ट, ऑब्जेक्ट के तरीकों और क्लास के स्टैटिक तरीकों को उन जगहों से कॉल कर सकती हैं जहां पहले से ही लाइब्रेरी के तरीकों को कॉल किया जा सकता था. इन जगहों में ये शामिल हैं:

यहां दिए गए 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 प्रोजेक्ट खोलें. इसके बाद, बाईं ओर मौजूद एक्ज़ीक्यूशन पर क्लिक करें.

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

क्लास

क्लास, इनहेरिटेंस के साथ कोड को कॉन्सेप्ट के हिसाब से व्यवस्थित करने का एक तरीका है. 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 एनवायरमेंट से कोड के उदाहरणों को अडैप्ट करते समय, कंपैटिबिलिटी से जुड़ी समस्याएं आ सकती हैं.

उपलब्ध न होने वाले एपीआई

Apps Script V8 रनटाइम में, नीचे दिए गए स्टैंडर्ड JavaScript एपीआई उपलब्ध नहीं हैं:

  • टाइमर: setTimeout, setInterval, clearTimeout, clearInterval
  • स्ट्रीम: ReadableStream, WritableStream, TextEncoder, TextDecoder
  • वेब एपीआई: fetch, FormData, File, Blob, URL, URLSearchParams, DOMException, atob, btoa
  • Crypto: crypto, SubtleCrypto
  • ग्लोबल ऑब्जेक्ट: window, navigator, performance, process (Node.js)

Apps Script API के इन विकल्पों का इस्तेमाल करें:

  • टाइमर: सिंक्रोनस पॉज़ के लिए, Utilities.sleep का इस्तेमाल करें. एसिंक्रोनस टाइमर काम नहीं करते.
  • फ़ेच करना: एचटीटीपी(एस) अनुरोध करने के लिए, UrlFetchApp.fetch(url, params) का इस्तेमाल करें.
  • atob: Base64 कोड में बदली गई स्ट्रिंग को डिकोड करने के लिए, Utilities.base64Decode का इस्तेमाल करें.
  • btoa: Base64 में स्ट्रिंग को एन्कोड करने के लिए, Utilities.base64Encode का इस्तेमाल करें.
  • क्रिप्टो: क्रिप्टोग्राफ़िक फ़ंक्शन के लिए Utilities का इस्तेमाल करें. जैसे, computeDigest, computeHmacSha256Signature, और computeRsaSha256Signature.

जिन एपीआई के लिए Apps Script का विकल्प उपलब्ध नहीं है उनके लिए, कभी-कभी पॉलीफ़िल का इस्तेमाल किया जा सकता है. जैसे, TextEncoder. पॉलीफ़िल एक ऐसी लाइब्रेरी होती है जो एपीआई की उस सुविधा को दोहराती है जो रनटाइम एनवायरमेंट में डिफ़ॉल्ट रूप से उपलब्ध नहीं होती. किसी पॉलीफ़िल का इस्तेमाल करने से पहले, पक्का करें कि वह Apps Script के V8 रनटाइम के साथ काम करता हो.

एसिंक्रोनस से जुड़ी सीमाएं

V8 रनटाइम, async और await सिंटैक्स के साथ-साथ Promise ऑब्जेक्ट के साथ काम करता है. हालांकि, Apps Script का रनटाइम एनवायरमेंट बुनियादी तौर पर सिंक्रोनस होता है.

  • माइक्रोटास्क (सपोर्ट किया जाता है): रनटाइम, माइक्रोटास्क की कतार को प्रोसेस करता है. इसमें Promise.then कॉलबैक और await रिज़ॉल्यूशन होते हैं. यह प्रोसेस, मौजूदा कॉल स्टैक के क्लियर होने के बाद होती है.
  • मैक्रोटास्क (काम नहीं करता): Apps Script में मैक्रोटास्क के लिए स्टैंडर्ड इवेंट लूप नहीं होता. setTimeout और setInterval जैसे फ़ंक्शन उपलब्ध नहीं हैं.
  • WebAssembly अपवाद: 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 पर स्विच किया जा सकता है. इसके लिए, यह तरीका अपनाएं:

  1. Apps Script प्रोजेक्ट खोलें.
  2. बाईं ओर, प्रोजेक्ट सेटिंग पर क्लिक करें.
  3. Chrome V8 रनटाइम चालू करें चेकबॉक्स को चुनें.

इसके अलावा, स्क्रिप्ट मेनिफ़ेस्ट में बदलाव करके, स्क्रिप्ट रनटाइम को सीधे तौर पर सेट किया जा सकता है:

  1. Apps Script प्रोजेक्ट खोलें.
  2. बाईं ओर, प्रोजेक्ट सेटिंग पर क्लिक करें.
  3. मेनिफ़ेस्ट फ़ाइल "appsscript.json" एडिटर में दिखाएं चेकबॉक्स को चुनें.
  4. बाईं ओर, एडिटर > appsscript.json पर क्लिक करें.
  5. appsscript.json मेनिफ़ेस्ट फ़ाइल में, runtimeVersion फ़ील्ड को V8 वैल्यू पर सेट करें.
  6. सबसे ऊपर, प्रोजेक्ट सेव करें पर क्लिक करें.

V8 पर स्क्रिप्ट माइग्रेट करना लेख में, अन्य चरणों के बारे में बताया गया है. इन चरणों को पूरा करके, यह पक्का किया जा सकता है कि आपकी स्क्रिप्ट, V8 का इस्तेमाल करके ठीक से काम करे.

Rhino रनटाइम चालू करना

अगर आपकी स्क्रिप्ट V8 का इस्तेमाल कर रही है और आपको इसे ओरिजनल Rhino रनटाइम पर स्विच करना है, तो यह तरीका अपनाएं:

  1. Apps Script प्रोजेक्ट खोलें.
  2. बाईं ओर, प्रोजेक्ट सेटिंग पर क्लिक करें.
  3. Chrome V8 रनटाइम चालू करें चेकबॉक्स से सही का निशान हटाएं.

इसके अलावा, स्क्रिप्ट के मेनिफ़ेस्ट में बदलाव करें:

  1. Apps Script प्रोजेक्ट खोलें.
  2. बाईं ओर, प्रोजेक्ट सेटिंग पर क्लिक करें.
  3. मेनिफ़ेस्ट फ़ाइल "appsscript.json" एडिटर में दिखाएं चेकबॉक्स को चुनें.
  4. बाईं ओर, एडिटर > appsscript.json पर क्लिक करें.
  5. appsscript.json मेनिफ़ेस्ट फ़ाइल में, runtimeVersion फ़ील्ड को DEPRECATED_ES5 वैल्यू पर सेट करें.
  6. सबसे ऊपर, प्रोजेक्ट सेव करें पर क्लिक करें.

मैं मौजूदा स्क्रिप्ट कैसे माइग्रेट करूं?

V8 पर स्क्रिप्ट माइग्रेट करना गाइड में, मौजूदा स्क्रिप्ट को V8 का इस्तेमाल करने के लिए माइग्रेट करने का तरीका बताया गया है. इसके लिए, V8 रनटाइम चालू करना होगा. साथ ही, स्क्रिप्ट की जांच करके यह देखना होगा कि वह V8 रनटाइम के साथ काम करती है या नहीं.

स्क्रिप्ट को V8 पर अपने-आप माइग्रेट करने की सुविधा

Google, 18 फ़रवरी, 2020 से उन मौजूदा स्क्रिप्ट को V8 पर माइग्रेट करना शुरू कर देगा जो अपने-आप होने वाली कंपैटिबिलिटी की जांच में पास हो जाती हैं. माइग्रेशन के बाद, प्रभावित स्क्रिप्ट सामान्य रूप से काम करती रहेंगी.

अगर आपको किसी स्क्रिप्ट को अपने-आप माइग्रेट होने से रोकना है, तो उसके मेनिफ़ेस्ट में मौजूद runtimeVersion फ़ील्ड को DEPRECATED_ES5 पर सेट करें. इसके बाद, आपके पास किसी भी समय स्क्रिप्ट को मैन्युअल तरीके से V8 पर माइग्रेट करने का विकल्प होता है.

मैं गड़बड़ियों की शिकायत कैसे करूं?

सहायता गाइड में, Stack Overflow पर प्रोग्रामिंग से जुड़ी मदद पाने, समस्याओं की मौजूदा रिपोर्ट खोजने, नई गड़बड़ियों की शिकायत करने, और नई सुविधाओं के लिए अनुरोध करने का तरीका बताया गया है.