mhgp
@mhgp

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Google Apps Script のデバッガがハングアップしてしまう

Discussion

Closed

解決したいこと

Google Apps Script のデバッガが、日本語の文を代入した変数を扱おうとしたときにハングアップしてしまう問題を解決ないし、回避したい。

発生している問題・エラー

正確な条件はよくわかっていないが、少なくとも次の条件を満たす文字列が代入された変数があるとそれを表示しようとしたときにハングアップしてしまう(少なくとも10秒待っても先に進まなくなってしまう)。

  • UTF-8において2バイト以上になる文字で構成される
  • 合計201バイト以上の長さ

該当するソースコード

67文字のあ
function test() {
  const foo = 'あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  debugger;
}

上記コードをデバッグで実行した場合、デバッガが次の画像のようになったまま先に進まなくなってしまう。

image.png

自分で試したこと

  • を「66文字」と「67文字」で試すと、後者はハングしてしまう。
  • ©も同様に「100文字」と「101文字」で試すと、後者がハングしてしまう。
  • 𐌱も同様。「50文字」と「50文字+a」の場合は、後者でハング。
  • aを202文字にした場合ではハングしない。
  • 2つの異なるアカウントで試したが同様の結果になった。
  • 'use strict'であるかどうかは関係がなさそう。
  • Rhino ランタイムで試そうとしたが、そもそもデバッガが対応していなかったため失敗に終わった。

以下、その他の試行。

が67文字連続した文字列の場合はハングしてしまう。

NG
function test1_1() {
  const foo = 'あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  debugger;
}

先頭にaをつけただけでハングしなくなる場合がある。

OK
function test1_2() {
  const foo = 'aあああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  debugger;
}

アルファベットの混合だけでは回避できない。

NG
function test2() {
  let foo = 'このスクリプトは、 Google Apps Script のデバッガがハングアップしてしまう問題の確認用に作成しました。条件は不明ながら、一定の条件を満たす文字列が代入された変数を扱おうとするとデバッガはフリーズしてしまうようです。';
  debugger;
}

再代入で条件を満たさない文字列になった場合はハングしない。例えば次のコードの場合、①の位置で止めるとハングするが、②の位置ではハングしない。

function test3() {
  let foo = 'あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  //①
  foo = 'a';
  //②
}

オブジェクトに値として代入した場合もダメなよう。

NG
function test4() {
  const foo = {
    1: 'あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ'
  };
  debugger;
}

Mapオブジェクトの場合はうまくいった。

OK
function test5() {
  const foo = new Map([
    [1, 'あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ'],
  ]);
  debugger;
}
0

確かにtest1_1関数をデバッグにかけると応答が無いためか、リクエストをくり返してるようです。

回避方法としてnew String('文字列')ぐらいでしょうか(ただLocal変数のツリーを開こうとするとハングアップする)。


その気があるようでしたらGoogleにフィードバックしてみてください。いちいちnew String()は少ししんどいです。

0Like

@STSynthe
ご回答ありがとうございます。

応答が無いためか、リクエストをくり返してるようです。

問題の生じない次のコードで試してみたところ、ハングアップしているかどうかに関わらずPOST通信は定期的に発生しているようです。

function test_en() {
  const foo = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
  debugger;
}

もしデバッガーがハングしたことが理由と判断された根拠が、通信が定期的に発生している以外にあるのであれば今後の参考にしたいので教えていただけると幸いです。

その気があるようでしたらGoogleにフィードバックしてみてください。

頑張ってみようかなとは思うのですが、英語が壊滅的なので時間がかかりそうです。
Google Issue Trackerでそれっぽい単語を入力して調べてみたところ、次の報告が今回の問題に相当しそうな気がします。
https://issuetracker.google.com/issues/190539180

多分コメントに簡単な説明と、ここで掲載した NG コードを合わせて投稿すればよいのだと思うのですが、文化的にこうした方が良いなどのアドバイスはありますか?

0Like

ハングアップしているかどうかに関わらずPOST通信は定期的に発生しているようです。

端折り過ぎたようで失礼しました。

どのコートでもデバッグ中、定期的にリクエストをくり返してますが、問題のコードだけは応答が長く、リトライが発生してるように見えます。

文化的にこうした方が

当方も経験は少ないので。しかし強いて言うなら

  • 日本人アピールをしない
  • ChatGPTに頼らない。自分の知らない知識を求めるとアレは平気で嘘をつくので、Google翻訳、DeepL翻訳などを使う。
  • 無理に長文にせず、要点が短くまとまっていれば良い。
  • 記事を読んでくれた事への感謝を伝える(「ありがとう」程度で良い)

aを202文字にした場合ではハングしない。

コレが少し気がかりで、ザックリとした検証しかしていませんが、202 byte以降、3 byte毎なら動作するようです。

// Work
function test_199byte() {
  const foo = '*ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Work
function test_200byte() {
  const foo = '**ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Not work
function test_201byte() {
  const foo = '**1ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Work
function test_202byte() {
  const foo = '**12ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Not work
function test_203byte() {
  const foo = '**123ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Not work
function test_204byte() {
  const foo = '**1234ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Work
function test_205byte() {
  const foo = '**12345ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Not work
function test_206byte() {
  const foo = '**123456ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Not work
function test_207byte() {
  const foo = '**1234567ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Work
function test_208byte() {
  const foo = '**12345678ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}

// Work
function test_211byte() {
  const foo = '**12345678901ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ';
  Logger.log('length: %d', foo.length);
  debugger;
}
1Like

@STSynthe
ご返信ありがとうございます。
おかげさまで無事コメントを投稿できました。

複雑なことは書けそうになかったので、200バイトあたりで問題が起きることと、その実証コードを掲載しました。
恐らくVasan様が述べていたように、デバッガーの切りつめ表示機能あたりに問題があるのだと思います。

コメントに掲載した次のコード(一部抜粋)は、STSynthe様の新しい実験コードから着想を得ました。ありがとうございます:smiley:

/*-------- TEST: 3 byte character --------*/
// Ok
function test_3byteChar_1() {
  const str = [
    '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890',
    '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567',
    ''
  ].join('');
  Logger.log('total: %d byte', computeStringByteByUtf8_(str)); //200 byte
  debugger;
}
// Hang!
function test_3byteChar_2() {
  const str = [
    '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890',
    '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678',
    ''
  ].join('');
  Logger.log('total: %d byte', computeStringByteByUtf8_(str)); //201 byte
  debugger;
}
// Ok
function test_3byteChar_3() {
  const str = [
    '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890',
    '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',
    ''
  ].join('');
  Logger.log('total: %d byte', computeStringByteByUtf8_(str)); //202 byte
  debugger;
}

/*-------- Utility --------*/
const computeStringByteByUtf8_ = (str) => {
  return Utilities.newBlob('', 'text/plain', '').setDataFromString(str, 'UTF-8').getBytes().length;
};
0Like

Your answer might help someone💌