Komut dosyalarını V8 çalışma zamanına taşıma

Rhino çalışma zamanını kullanan mevcut bir komut dosyanız varsa ve komut dosyasını V8'e taşımanız gerekir.

Rhino çalışma zamanı kullanılarak yazılan çoğu komut dosyası, V8 çalışma zamanı ile çalışabilir gerçekleşiyor. Bir komut dosyasına V8 söz dizimi ve özellikleri eklemenin tek ön koşulu genellikle V8 çalışma zamanını etkinleştirmektir.

Ancak V8 çalışma zamanını etkinleştirdikten sonra komut dosyasının başarısız olmasına veya beklenmedik şekilde davranmasına neden olabilecek küçük bir uyumsuzluk ve diğer farklılıklar vardır. Taşıma sırasında komut dosyası oluşturduktan sonra bu sorunları ve komut dosyası projesini düzeltin.

V8 taşıma prosedürü

Bir komut dosyasını V8'e taşımak için şu prosedürü uygulayın:

  1. V8 çalışma zamanını etkinleştirme tercih edebilirsiniz.
  2. Uyumsuzlukları dikkatlice inceleyin aşağıda listelenmiştir. Aşağıdakilerden herhangi birinin mevcut olup olmadığını belirlemek için komut dosyanızı inceleyin: mevcut uyumsuzluklar var. bir veya daha fazla uyumsuzluk varsa sorunu gidermek veya önlemek için komut dosyası kodunuzu ayarlayın.
  3. Aşağıda listelenen diğer farklılıkları dikkatlice inceleyin. Listelenen farklılıklardan herhangi birinin etkili olup olmadığını belirlemek için komut dosyanızı inceleyin. kodunuzun davranışını gösterir. Komut dosyanızı bu davranışı düzeltecek şekilde düzenleyin.
  4. Tespit edilen uyumsuzlukları veya diğer farklılıkları düzelttikten sonra, kodunuzu V8 söz dizimini ve diğer özellikleri istediğiniz gibi kullanacak şekilde güncellemeye başlayabilirsiniz.
  5. Kod ayarlamalarınızı tamamladıktan sonra, ve beklendiği gibi işlediğinden emin olmaktır.
  6. Komut dosyanız bir web uygulaması veya yayınlanmış eklenti ise yapman gereken yeni bir sürüm oluşturun komut dosyasının V8 düzenlemelerine sahip olmasını sağlayın. V8 sürümünü kullanıyorsanız komut dosyasını bu sürümle yeniden yayınlamanız gerekir.

Uyumsuzluklar

Rhino tabanlı orijinal Apps Komut Dosyası çalışma zamanı maalesef birçok standart dışı ECMAScript davranışları. V8 standartlara uygun olduğundan bu davranışlar taşıma işleminden sonra desteklenmez. Bu sorunların düzeltilmemesi V8 çalışma zamanı etkinleştirildiğinde hatalara veya bozuk komut dosyası davranışına neden olur.

Aşağıdaki bölümlerde bu davranışların her biri ve uygulamanız gereken adımlar açıklanmaktadır kullanarak V8'e geçiş sırasında komut dosyası kodunuzu düzeltin.

for each(variable in object) kullanmaktan kaçının

İlgili içeriği oluşturmak için kullanılan for each (variable in object) ifadesi, JavaScript 1.6'ya eklendi ve for...of lehine kaldırıldı.

Komut dosyanızı V8'e taşırken for each (variable in object) kullanmaktan kaçının. ifadeleri.

Bunun yerine for (variable in object) işlevini kullanın:

// Rhino runtime
var obj = {a: 1, b: 2, c: 3};

// Don't use 'for each' in V8
for each (var value in obj) {
  Logger.log("value = %s", value);
}
      
// V8 runtime
var obj = {a: 1, b: 2, c: 3};

for (var key in obj) {  // OK in V8
  var value = obj[key];
  Logger.log("value = %s", value);
}
      

Date.prototype.getYear() kullanmaktan kaçının

Orijinal Rhino çalışma zamanında Date.prototype.getYear() 1900-1999 yılları için iki basamaklı yılları, diğer yıllar için ise dört basamaklı yılları döndürür tarihlerine göre düzenlenmiştir.

V8 çalışma zamanında, Date.prototype.getYear() şunun yerine, yılı eksi 1900 çıkarıp döndürür dahil edilir.

Komut dosyanızı V8'e taşırken her zaman Date.prototype.getFullYear(), tarihi ne olursa olsun dört basamaklı bir yıl döndürür.

Ayrılmış anahtar kelimeleri ad olarak kullanmaktan kaçının

ECMAScript, bazı dokümanların ayırtılmış anahtar kelimeler kullanabilirsiniz. Rhino çalışma zamanı bu kelimelerin çoğuna izin verdi bu nedenle, kodunuz bunları kullanıyorsa işlevlerinizi veya değişkenlerinizi yeniden adlandırmanız gerekir.

Komut dosyanızı V8'e taşırken değişkeni veya işlevleri adlandırmaktan kaçının ayırtılmış anahtar kelimeler bölümüne bakın. Anahtar kelime adını kullanmaktan kaçınmak için değişkenleri veya işlevleri yeniden adlandırın. Yaygın kullanım şekilleri class, import ve export gibi anahtar kelimeler bulunuyor.

const değişkenini yeniden atamaktan kaçının

Orijinal Rhino çalışma zamanında, son haline getirmek için const kullanarak sembolün değerinin hiçbir zaman değişmemesi ve simgeleri göz ardı edilir.

Yeni V8 çalışma zamanında, const anahtar kelimesi standart olarak uyumludur ve const olarak tanımlanan bir değişkene dönüştürmek, TypeError: Assignment to constant variable çalışma zamanı hatası.

Komut dosyanızı V8'e taşırken, bir const değişkeni görebilirsiniz:

// Rhino runtime
const x = 1;
x = 2;          // No error
console.log(x); // Outputs 1
      
// V8 runtime
const x = 1;
x = 2;          // Throws TypeError
console.log(x); // Never executed
      

Değişmez XML değerlerinden ve XML nesnesinden kaçının.

Bu standart olmayan uzantı yayınlamak, Apps Komut Dosyası projelerinin doğrudan XML söz dizimini kullanmasına olanak tanır.

Komut dosyanızı V8'e taşırken doğrudan XML değişmez değerlerini veya XML'yi kullanmaktan kaçının. nesne.

Bunun yerine, XML'i ayrıştırmak için XmlService'i kullanın:

// V8 runtime
var incompatibleXml1 = <container><item/></container>;             // Don't use
var incompatibleXml2 = new XML('<container><item/></container>');  // Don't use

var xml3 = XmlService.parse('<container><item/></container>');     // OK
      

__iterator__ kullanarak özel iteratör işlevleri oluşturmayın

JavaScript 1.7, sınıfın prototipinde bir __iterator__ işlevi tanımlayarak herhangi bir sınıfa özel bir iteratör ekleme olanağı sağlayan bir özellik ekledi. Bu özellik, geliştiricilere kolaylık sağlamak amacıyla Apps Script'in Rhino çalışma zamanında da eklendi. Ancak, bu özellik ECMA-262 standardı ve ECMAScript uyumlu JavaScript motorlarında kaldırılmıştır. V8 kullanan komut dosyaları bu iteratör yapısını kullanamaz.

Komut dosyanızı V8'e taşırken derlemek için __iterator__ işlevinden kaçının özel iterasyonlar. Bunun yerine ECMAScript 6 yinelemelerini kullanın.

Aşağıdaki dizi yapısını ele alalım:

// Create a sample array
var myArray = ['a', 'b', 'c'];
// Add a property to the array
myArray.foo = 'bar';

// The default behavior for an array is to return keys of all properties,
//  including 'foo'.
Logger.log("Normal for...in loop:");
for (var item in myArray) {
  Logger.log(item);            // Logs 0, 1, 2, foo
}

// To only log the array values with `for..in`, a custom iterator can be used.
      

Aşağıdaki kod örnekleri, Rhino çalışma zamanında bir iteratörün nasıl oluşturulabileceğini ve V8 çalışma zamanında bir değişim iteratörünün nasıl oluşturulabileceğini gösterir:

// Rhino runtime custom iterator
function ArrayIterator(array) {
  this.array = array;
  this.currentIndex = 0;
}

ArrayIterator.prototype.next = function() {
  if (this.currentIndex
      >= this.array.length) {
    throw StopIteration;
  }
  return "[" + this.currentIndex
    + "]=" + this.array[this.currentIndex++];
};

// Direct myArray to use the custom iterator
myArray.__iterator__ = function() {
  return new ArrayIterator(this);
}


Logger.log("With custom Rhino iterator:");
for (var item in myArray) {
  // Logs [0]=a, [1]=b, [2]=c
  Logger.log(item);
}
      
// V8 runtime (ECMAScript 6) custom iterator
myArray[Symbol.iterator] = function() {
  var currentIndex = 0;
  var array = this;

  return {
    next: function() {
      if (currentIndex < array.length) {
        return {
          value: "[${currentIndex}]="
            + array[currentIndex++],
          done: false};
      } else {
        return {done: true};
      }
    }
  };
}

Logger.log("With V8 custom iterator:");
// Must use for...of since
//   for...in doesn't expect an iterable.
for (var item of myArray) {
  // Logs [0]=a, [1]=b, [2]=c
  Logger.log(item);
}
      

Koşullu yakalama ifadeleri kullanmaktan kaçının

V8 çalışma zamanı, catch..if koşullu yakalama deyimlerini desteklemez birlikte kullanıldığında standartlarla uyumlu değildir.

Komut dosyanızı V8'e taşırken, catch koşullularını catch gövdesinin içine taşıyın:

// Rhino runtime

try {
  doSomething();
} catch (e if e instanceof TypeError) {  // Don't use
  // Handle exception
}
      
// V8 runtime
try {
  doSomething();
} catch (e) {
  if (e instanceof TypeError) {
    // Handle exception
  }
}

Object.prototype.toSource() kullanmaktan kaçının

JavaScript 1.3, Object.prototype.toSource() bir ECMAScript standardının parçası olmayan eski yöntemler kullanır. V8 çalışma zamanında desteklenmez.

Komut dosyanızı V8'e taşırken, Object.prototype.toSource() kodunuzdan kaldırın.

Diğer farklılıklar

Komut dosyası hatalarına neden olabilecek yukarıdaki uyumsuzluklara ek olarak, düzeltilmezse beklenmedik V8'e neden olabilecek diğer birkaç farklılık çalışma zamanı komut dosyası davranışı.

Aşağıdaki bölümlerde, bu sorunlardan kaçınmak için komut dosyası kodunuzu nasıl güncelleyebileceğiniz açıklanmaktadır. beklenmedik sürprizler.

Yerel ayara özel tarih ve saat biçimlendirmesini ayarla

Date yöntem toLocaleString(), toLocaleDateString(), ve toLocaleTimeString() belirli bir çok daha farklı sonuçlar veriyor.

Rhino'da varsayılan biçim long format ve yoksayılır.

V8 çalışma zamanında varsayılan biçim kısa biçim ve parametrelerdir. ECMA standardına göre ele alınır (bkz. toLocaleDateString() belgeleri bakın).

Kodunuzu V8'e taşırken yerel ayara özgü tarih ve saat yöntemlerinin çıkışıyla ilgili kodunuzun beklentilerini test edip düzenleyin:

// Rhino runtime
var event = new Date(
  Date.UTC(2012, 11, 21, 12));

// Outputs "December 21, 2012" in Rhino
console.log(event.toLocaleDateString());

// Also outputs "December 21, 2012",
//  ignoring the parameters passed in.
console.log(event.toLocaleDateString(
    'de-DE',
    { year: 'numeric',
      month: 'long',
      day: 'numeric' }));
// V8 runtime
var event = new Date(
  Date.UTC(2012, 11, 21, 12));

// Outputs "12/21/2012" in V8
console.log(event.toLocaleDateString());

// Outputs "21. Dezember 2012"
console.log(event.toLocaleDateString(
    'de-DE',
    { year: 'numeric',
      month: 'long',
      day: 'numeric' }));
      

Error.fileName ve Error.lineNumber kullanmaktan kaçının

V8 zamanında, standart JavaScript Error nesne, fileName veya lineNumber parametresini kurucu parametreler olarak desteklemiyor özellikleri olabilir.

Komut dosyanızı V8'e taşırken, Error.fileName ve Error.lineNumber ile ilişkili tüm bağımlılıkları kaldırın.

Alternatif olarak, Error.prototype.stack. Bu yığın da standart dışıdır ancak hem Rhino hem de V8'de desteklenir. İlgili içeriği oluşturmak için kullanılan iki platform tarafından oluşturulan yığın izlemenin (stack trace) biçimi biraz farklıdır:

// Rhino runtime Error.prototype.stack
// stack trace format
at filename:92 (innerFunction)
at filename:97 (outerFunction)
// V8 runtime Error.prototype.stack
// stack trace format
Error: error message
at innerFunction (filename:92:11)
at outerFunction (filename:97:5)
      

Dizeleştirilmiş enum nesnelerinin işlenmesini ayarlama

Orijinal Rhino çalışma zamanında JavaScript'i kullanarak JSON.stringify() yöntemi yalnızca {} değerini döndürür.

V8'de, bir numaralandırma nesnesinde aynı yöntemin kullanılması enum adını geri alır.

Komut dosyanızı V8'e taşırken, kodunuzun çıktıyla ilgili beklentilerini test etme ve ayarlama JSON.stringify() enum nesnelerinde:

// Rhino runtime
var enumName =
  JSON.stringify(Charts.ChartType.BUBBLE);

// enumName evaluates to {}
// V8 runtime
var enumName =
  JSON.stringify(Charts.ChartType.BUBBLE);

// enumName evaluates to "BUBBLE"

Tanımlanmamış parametrelerin işlenmesini ayarlayın

Orijinal Rhino çalışma zamanında, undefined parametresi bir yönteme parametre olarak iletiliyor ile sonuçlandığı gibi, "undefined" dizesinin bu yönteme iletilmesiyle sonuçlanmıştır.

V8'de, undefined yönteminin yöntemlere aktarılması, null değerinin iletilmesiyle eşdeğerdir.

Komut dosyanızı V8'e taşırken, kodunuzun undefined parametreleriyle ilgili beklentilerini test edin ve ayarlayın:

// Rhino runtime
SpreadsheetApp.getActiveRange()
    .setValue(undefined);

// The active range now has the string
// "undefined"  as its value.
      
// V8 runtime
SpreadsheetApp.getActiveRange()
    .setValue(undefined);

// The active range now has no content, as
// setValue(null) removes content from
// ranges.

Global this için işlenmeyi ayarlayın

Rhino çalışma zamanı, bunu kullanan komut dosyaları için örtülü özel bir bağlam tanımlar. Komut dosyası kodu, gerçek global koddan farklı olarak, bu örtülü bağlamda çalışır. this Bu, "genel this" referansları anlamına gelir koda eklemeli yalnızca kodu ve değişkenleri içeren özel bağlamı değerlendirerek komut dosyasında tanımlanmıştır. Yerleşik Apps Komut Dosyası hizmetleri ve ECMAScript nesneleri, this'ün bu kullanımından hariç tutulur. Bu durum şuna benziyordu: JavaScript yapısı:

// Rhino runtime

// Apps Script built-in services defined here, in the actual global context.
var SpreadsheetApp = {
  openById: function() { ... }
  getActive: function() { ... }
  // etc.
};

function() {
  // Implicit special context; all your code goes here. If the global this
  // is referenced in your code, it only contains elements from this context.

  // Any global variables you defined.
  var x = 42;

  // Your script functions.
  function myFunction() {
    ...
  }
  // End of your code.
}();

V8'de, örtülü özel bağlam kaldırılır. Genel değişkenler ve işlevler yerel bağlama yerleştirilir ve Apps Komut Dosyası hizmetleri ile Math ve Date gibi ECMAScript yerleşik entegrasyonları.

Komut dosyanızı V8'e taşırken kodunuzun beklentilerini test edin ve ayarlayın this kullanımı hakkında genel bilgi verdi. Çoğu durumda, ve kodunuz yalnızca öğenin anahtarlarını veya özellik adlarını incelediğinde genel this nesnesi:

// Rhino runtime
var myGlobal = 5;

function myFunction() {

  // Only logs [myFunction, myGlobal];
  console.log(Object.keys(this));

  // Only logs [myFunction, myGlobal];
  console.log(
    Object.getOwnPropertyNames(this));
}





      
// V8 runtime
var myGlobal = 5;

function myFunction() {

  // Logs an array that includes the names
  // of Apps Script services
  // (CalendarApp, GmailApp, etc.) in
  // addition to myFunction and myGlobal.
  console.log(Object.keys(this));

  // Logs an array that includes the same
  // values as above, and also includes
  // ECMAScript built-ins like Math, Date,
  // and Object.
  console.log(
    Object.getOwnPropertyNames(this));
}

Kitaplıklarda instanceof öğelerinin işlenmesini ayarlama

Başka bir projedeki işlevde parametre olarak iletilen bir nesnede kitaplıkta instanceof kullanılması yanlış negatif sonuç verebilir. V8 çalışma zamanında ve kitaplıkları farklı yürütme bağlamlarında çalıştırıldığı için zincirleri mevcut.

Bunun yalnızca kitaplığınız projenizde oluşturulmayan bir nesnede instanceof kullanıyorsa geçerli olduğunu unutmayın. Bu örneği, oluşturma sırasında oluşturulan bir nesnede ister projenizde aynı isterse farklı bir komut dosyasıyla olsun, beklendiği gibi çalışmalıdır.

V8 üzerinde çalışan bir proje komut dosyanızı kitaplık olarak kullanıyorsa komut dosyası, başka bir projeden aktarılacak bir parametrede instanceof kullanıyor. Ayarlayın: instanceof kullanımını ve kullanımınıza göre diğer uygun alternatifleri kullanmanızı öneririz. destek kaydı oluşturun.

a instanceof b için bir alternatif, a oluşturucusunu Bu durumlarda, prototip zincirinin tamamında arama yapmanız gerekmez ve hazırlayan kullanıcıdır. Kullanım: a.constructor.name == "b"

A Projesi'nin B Projesi'ni kitaplık olarak kullandığı A Projesi ile B Projesi'ni düşünün.

//Rhino runtime

//Project A

function caller() {
   var date = new Date();
   // Returns true
   return B.callee(date);
}

//Project B

function callee(date) {
   // Returns true
   return(date instanceof Date);
}

      
//V8 runtime

//Project A

function caller() {
   var date = new Date();
   // Returns false
   return B.callee(date);
}

//Project B

function callee(date) {
   // Incorrectly returns false
   return(date instanceof Date);
   // Consider using return (date.constructor.name ==
   // Date) instead.
   // return (date.constructor.name == Date) -> Returns
   // true
}

Diğer bir alternatif de ana projede instanceof değerini kontrol eden ve bir kitaplık işlevi çağırırken diğer parametrelere ek olarak işlevi de iletmek için bir işlev eklemektir. İletilen işlev ardından instanceof kitaplığını kontrol etmek için kullanılabilir.

//V8 runtime

//Project A

function caller() {
   var date = new Date();
   // Returns True
   return B.callee(date, date => date instanceof Date);
}

//Project B

function callee(date, checkInstanceOf) {
  // Returns True
  return checkInstanceOf(date);
}
      

Paylaşılmayan kaynakların kitaplıklara iletimini ayarlama

Paylaşılmayan bir kaynağın ana komut dosyasından kitaplığa iletilmesi, V8 çalışma zamanında farklı şekilde çalışır.

Rhino çalışma zamanında paylaşılmayan bir kaynağın iletilmesi işe yaramaz. Kitaplık bunun yerine kendi kaynağını kullanır.

V8 çalışma zamanında, paylaşılmayan bir kaynağı kitaplığa aktarmak işe yarar. Kitaplık, iletilen paylaşılmayan kaynağı kullanır.

Paylaşılmayan kaynakları işlev parametreleri olarak iletmeyin. Paylaşılmayan kaynakları her zaman, onları kullanan aynı komut dosyasında bildirin.

A Projesi’nin kitaplık olarak kullanıldığı A ve B projelerini düşünün. Bu örnekte, PropertiesService paylaşılmayan bir kaynaktır.

// Rhino runtime
// Project A
function testPassingNonSharedProperties() {
  PropertiesService.getScriptProperties()
      .setProperty('project', 'Project-A');
  B.setScriptProperties();
  // Prints: Project-B
  Logger.log(B.getScriptProperties(
      PropertiesService, 'project'));
}

//Project B function setScriptProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-B'); } function getScriptProperties( propertiesService, key) { return propertiesService.getScriptProperties() .getProperty(key); }

// V8 runtime
// Project A
function testPassingNonSharedProperties() {
  PropertiesService.getScriptProperties()
      .setProperty('project', 'Project-A');
  B.setScriptProperties();
  // Prints: Project-A
  Logger.log(B.getScriptProperties(
      PropertiesService, 'project'));
}

// Project B function setProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-B'); } function getScriptProperties( propertiesService, key) { return propertiesService.getScriptProperties() .getProperty(key); }

Bağımsız komut dosyalarına erişimi güncelleme

V8 çalışma zamanında çalışan bağımsız komut dosyaları için kullanıcılara en azından komut dosyası için görüntüleme erişimine sahip olması gerekir.