Rhino çalışma zamanı, 31 Ocak 2026 itibarıyla kullanımdan kaldırılacak. Rhino çalışma zamanını kullanan mevcut bir komut dosyanız varsa bu komut dosyasını V8'e taşımanız gerekir.
Genellikle V8 söz dizimi ve özelliklerini bir komut dosyasına eklemenin tek ön koşulu V8 çalışma zamanını etkinleştirmektir. Ancak, V8 çalışma zamanında bir 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 kümesi vardır. Bir komut dosyasını V8 kullanacak şekilde taşırken komut dosyası projesinde bu sorunları aramanız ve bulduğunuz sorunları düzeltmeniz gerekir.
V8'e taşıma prosedürü
Bir komut dosyasını V8'e taşımak için şu prosedürü uygulayın:
- Komut dosyası için V8 çalışma zamanını etkinleştirin.
runtimeVersion
, Apps Komut Dosyası projesinin manifest dosyası kullanılarak kontrol edilebilir. - Aşağıdaki uyumsuzlukları dikkatlice inceleyin. Uyumsuzluklardan herhangi birinin mevcut olup olmadığını belirlemek için komut dosyanızı inceleyin. Bir veya daha fazla uyumsuzluk varsa sorunu gidermek ya da önlemek için komut dosyası kodunuzu düzenleyin.
- Aşağıdaki diğer farklılıkları dikkatlice inceleyin. Listelenen farklılıklardan herhangi birinin kodunuzun davranışını etkileyip etkilemediğini belirlemek için komut dosyanızı inceleyin. Davranışı düzeltmek için komut dosyanızı ayarlayın.
- Tespit edilen uyumsuzlukları veya diğer farklılıkları düzelttikten sonra kodunuzu V8 söz dizimini ve diğer özellikleri kullanacak şekilde güncellemeye başlayabilirsiniz.
- Kod düzenlemelerinizi tamamladıktan sonra, komut dosyanızın beklendiği gibi çalıştığından emin olmak için komut dosyanızı kapsamlı bir şekilde test edin.
- Komut dosyanız bir web uygulamasıysa veya yayınlanmış bir eklentiyse, V8 düzenlemelerini içeren komut dosyasının yeni bir sürümünü oluşturmanız ve dağıtımı yeni oluşturulan sürüme yönlendirmeniz gerekir. V8 sürümünü kullanıcıların kullanımına sunmak için komut dosyasını bu sürümle yeniden yayınlamanız gerekir.
- Komut dosyanız kitaplık olarak kullanılıyorsa komut dosyanızın yeni bir sürüm oluşturulmuş dağıtımını oluşturun. Bu yeni sürümü, kitaplığınızı kullanan tüm komut dosyalarına ve kullanıcılara ileterek V8 özellikli sürüme güncellemelerini isteyin. Kitaplığınızın Rhino tabanlı eski sürümlerinin artık etkin olarak kullanılmadığını veya erişilebilir olmadığını doğrulayın.
- Komut dosyanızın hiçbir örneğinin eski Rhino çalışma zamanında çalışmadığını doğrulayın. Tüm dağıtımların V8 sürümünde olan bir sürümle ilişkilendirildiğini doğrulayın. Eski dağıtımları arşivleyin. Tüm sürümleri inceleyin ve V8 çalışma zamanını kullanmayan sürümleri silin.
Uyumsuzluklar
Orijinal Rhino tabanlı Apps Komut Dosyası çalışma zamanı maalesef birkaç standart dışı ECMAScript davranışına izin veriyordu. V8 standartlara uygun olduğundan bu davranışlar taşıma işleminden sonra desteklenmez. Bu sorunların düzeltilmemesi, V8 çalışma zamanı etkinleştirildikten sonra hatalara veya komut dosyası davranışının bozulmasına neden olur.
Aşağıdaki bölümlerde bu davranışların her biri ve V8'e geçiş sırasında komut dosyası kodunuzu düzeltmek için atmanız gereken adımlar açıklanmaktadır.
for each(variable in object)
kullanmaktan kaçının
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)
ifadelerini kullanmaktan kaçının.
Bunun yerine for (variable in object)
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 haneli yıllar, diğer tarihler için ise dört haneli yıllar döndürür. Bu, JavaScript 1.2 ve önceki sürümlerdeki davranıştı.
V8 çalışma zamanında,
Date.prototype.getYear()
ECMAScript standartlarının gerektirdiği şekilde yıl eksi 1900 değerini döndürür.
Komut dosyanızı V8'e taşırken her zaman
Date.prototype.getFullYear()
kullanın.
Bu işlev, tarihten bağımsız olarak dört haneli bir yıl döndürür.
Ayrılmış anahtar kelimeleri ad olarak kullanmaktan kaçının
ECMAScript, işlev ve değişken adlarında belirli ayrılmış anahtar kelimelerin kullanılmasını yasaklar. Rhino çalışma zamanı bu kelimelerin çoğuna izin veriyordu. Bu nedenle, kodunuzda bu kelimeler kullanılıyorsa işlevlerinizi veya değişkenlerinizi yeniden adlandırmanız gerekir.
Komut dosyanızı V8'e taşırken değişkenleri veya işlevleri ayrılmış anahtar kelimelerden birini kullanarak adlandırmayın.
Anahtar kelime adını kullanmamak için herhangi bir değişkeni veya işlevi yeniden adlandırın. Anahtar kelimelerin ad olarak yaygın kullanımları class
, import
ve export
'dir.
const
değişkenlerini yeniden atamaktan kaçının
Orijinal Rhino çalışma zamanında, const
kullanarak bir değişken bildirebilirsiniz. Bu, sembolün değerinin asla değişmediği ve sembole gelecekteki atamaların yoksayıldığı anlamına gelir.
Yeni V8 çalışma zamanında const
anahtar kelimesi standartlara uygundur ve const
olarak tanımlanan bir değişkene atama yapılması TypeError: Assignment to constant variable
çalışma zamanı hatasına neden olur.
Komut dosyanızı V8'e taşırken const
değişkeninin değerini yeniden atamaya çalışmayın:
// 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 |
XML değişmezlerinden ve XML nesnesinden kaçının
ECMAScript'in bu standart dışı uzantısı, 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şmezleri veya XML nesnesi kullanmaktan kaçının.
Bunun yerine, XML'yi 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 yineleyici işlevler oluşturmayın.
JavaScript 1.7, bir sınıfın prototipinde __iterator__
işlevi tanımlayarak herhangi bir sınıfa özel yineleyici eklemeye olanak tanıyan bir özellik ekledi. Bu özellik, geliştiricilerin rahatlığı için Apps Komut Dosyası'nın Rhino çalışma zamanına da eklendi. Ancak bu özellik hiçbir zaman ECMA-262 standardının bir parçası olmadı ve ECMAScript uyumlu JavaScript motorlarında kaldırıldı. V8 kullanan komut dosyaları bu yineleyici yapısını kullanamaz.
Komut dosyanızı V8'e taşırken __iterator__
işlevini kullanaraközel yineleyiciler oluşturmaktan kaçının. Bunun yerine ECMAScript 6 yineleyicilerini kullanın.
Aşağıdaki dizi yapısını inceleyin:
// 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 örneklerinde, Rhino çalışma zamanında bir yineleyicinin nasıl oluşturulabileceği ve V8 çalışma zamanında nasıl yedek yineleyici oluşturulacağı gösterilmektedir:
// 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 ifadelerinden kaçının
V8 çalışma zamanı, standartlara uygun olmadıkları için catch..if
koşullu yakalama ifadelerini desteklemez.
Komut dosyanızı V8'e taşırken tüm yakalama koşulları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, hiçbir zaman ECMAScript standardının parçası olmayan bir Object.prototype.toSource() yöntemi içeriyordu. V8 çalışma zamanında desteklenmez.
Komut dosyanızı V8'e taşırken kodunuzda Object.prototype.toSource() kullanımını kaldırın.
Diğer farklılıklar
Komut dosyası hatalarına neden olabilecek yukarıdaki uyumsuzluklara ek olarak, düzeltilmediği takdirde beklenmedik V8 çalışma zamanı komut dosyası davranışına yol açabilecek birkaç farklılık daha vardır.
Aşağıdaki bölümlerde, bu tür beklenmedik durumlarla karşılaşmamak için komut dosyası kodunuzu nasıl güncelleyeceğiniz açıklanmaktadır.
Yerel ayara özgü tarih ve saat biçimlendirmesini ayarlama
Date
yöntemleri toLocaleString()
,
toLocaleDateString()
,
ve toLocaleTimeString()
V8 çalışma zamanında Rhino'ya kıyasla farklı şekilde davranır.
Rhino'da varsayılan biçim uzun biçimdir ve iletilen tüm parametreler yoksayılır.
V8 çalışma zamanında varsayılan biçim kısa biçimdir ve iletilen parametreler ECMA standardına göre işlenir (ayrıntılar için toLocaleDateString()
dokümanlarına bakın).
V8'e geçiş yaparken kodunuzun yerel ayara özgü tarih ve saat yöntemlerinin çıkışıyla ilgili beklentilerini test edin ve ayarlayın:
// 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 çalışma zamanında, standart JavaScript
Error
nesnesi, oluşturucu parametreleri
veya nesne özellikleri olarak fileName
ya da lineNumber
değerlerini desteklemez.
Komut dosyanızı V8'e taşırken,
Error.fileName
ve Error.lineNumber
bağımlılıklarını kaldırın.
Alternatif olarak Error.prototype.stack
simgesini kullanabilirsiniz.
Bu yığın da standart dışıdır ancak V8'de desteklenir. İki platform tarafından oluşturulan yığın izinin 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, bir enum nesnesinde JavaScript
JSON.stringify()
yöntemini kullanmak yalnızca {}
değerini döndürür.
V8'de, aynı yöntemi bir enum nesnesinde kullanmak enum adını döndürür.
V8'e geçiş yaparken,
kodunuzun JSON.stringify()
numaralandırılmış nesnelerdeki çıkışıyla ilgili beklentilerini test edin ve ayarlayın:
// 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 ayarlama
Orijinal Rhino çalışma zamanında, bir yönteme parametre olarak undefined
iletildiğinde bu yönteme "undefined"
dizesi iletiliyordu.
V8'de yöntemlere undefined
iletmek, null
iletmeye 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şleme yöntemini ayarlayın
Rhino çalışma zamanı, kendisini kullanan komut dosyaları için örtülü bir özel bağlam tanımlar.
Komut dosyası kodu, gerçek global this
'dan farklı olarak bu örtülü bağlamda çalışır. Bu, kodda "global this
" referanslarının aslında yalnızca komut dosyasında tanımlanan kodu ve değişkenleri içeren özel bağlam olarak değerlendirildiği anlamına gelir. Yerleşik Apps Komut Dosyası hizmetleri ve ECMAScript nesneleri, this
kullanımının kapsamı dışındadır. Bu durum, aşağıdaki JavaScript yapısına benziyordu:
// 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. Komut dosyasında tanımlanan genel değişkenler ve işlevler, yerleşik Apps Komut Dosyası hizmetlerinin ve Math
ile Date
gibi ECMAScript yerleşiklerinin yanında genel bağlama yerleştirilir.
Komut dosyanızı V8'e taşırken kodunuzun, genel bağlamda this
kullanımına ilişkin beklentilerini test edin ve ayarlayın. Çoğu durumda, farklılıklar yalnızca kodunuz genel this
nesnesinin anahtarlarını veya özellik adlarını inceliyorsa belirgindir:
// 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
ile ilgili işlemleri ayarlama
Başka bir projedeki bir işlevde parametre olarak iletilen bir nesne üzerindeki bir kitaplıkta instanceof
kullanmak yanlış negatif sonuçlar verebilir. V8 çalışma zamanında, bir proje ve kitaplıkları farklı yürütme bağlamlarında çalıştırılır. Bu nedenle, farklı genel değişkenlere ve prototip zincirlerine sahiptirler.
Bu durumun yalnızca kitaplığınızda projenizde oluşturulmamış bir nesnede instanceof
kullanılıyorsa geçerli olduğunu unutmayın. Projenizde oluşturulan bir nesnede (projenizdeki aynı veya farklı bir komut dosyasında) kullanıldığında beklendiği gibi çalışır.
V8 üzerinde çalışan bir proje, komut dosyanızı kitaplık olarak kullanıyorsa komut dosyanızın başka bir projeden geçirilecek bir parametrede instanceof
kullanıp kullanmadığını kontrol edin. instanceof
kullanımını ayarlayın ve kullanım alanınıza göre diğer uygun alternatifleri kullanın.
a instanceof b
için bir alternatif, tüm prototip zincirinde arama yapmanız gerekmediği ve yalnızca oluşturucuyu kontrol etmeniz gereken durumlarda a
oluşturucusunu kullanmaktır.
Kullanım: a.constructor.name == "b"
Proje A'nın Proje B'yi kitaplık olarak kullandığı Proje A ve Proje B'yi ele alalım.
//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 } |
Başka bir alternatif olarak, ana projede instanceof
değerini kontrol eden bir işlev sunulabilir ve bir kitaplık işlevi çağrılırken işlev diğer parametrelerle birlikte iletilebilir. Daha sonra, geçirilen işlev kitaplıkta instanceof
değerini 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 aktarılmasını ayarlama
Ana komut dosyasından kitaplığa paylaşılmayan bir kaynağın aktarılması, V8 çalışma zamanında farklı şekilde çalışır.
Rhino çalışma zamanında, paylaşılmayan bir kaynağın iletilmesi çalışmaz. Kitaplık bunun yerine kendi kaynağını kullanır.
V8 çalışma zamanında, paylaşılan olmayan bir kaynağı kitaplığa aktarmak mümkündür. Kitaplık, iletilen paylaşılmayan kaynağı kullanır.
Paylaşılmayan kaynakları işlev parametresi olarak iletmeyin. Paylaşılmayan kaynakları her zaman bunları kullanan aynı komut dosyasında bildirin.
Proje A'nın Proje B'yi kitaplık olarak kullandığı Proje A ve Proje B'yi ele alalım. 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')); } |
// V8 runtime // Project A function testPassingNonSharedProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-A'); B.setScriptProperties(); // Prints: Project-A Logger.log(B.getScriptProperties( PropertiesService, 'project')); } |
Bağımsız komut dosyalarına erişimi güncelleme
V8 çalışma zamanında çalışan bağımsız komut dosyalarının tetikleyicilerinin düzgün çalışması için kullanıcılara komut dosyasına en az görüntüleme erişimi vermeniz gerekir.