AppleScriptでHTML解析

いよいよスプラトゥーン2の発売が迫り子供のお強請りが正に言葉通り凄まじくなって来たので、と言うのが今回の要件です。

実際にはこの初版運用から4回の販売があり、初めの3回は iPhone のメール通知の発見に遅れたためプッシュ通知が確実なメッセージアプリの利用に変更しました。4回目は通知が来たものの5分間隔では時既に遅しと言うことで、巡回の間隔を短くしました。

解析というほど大袈裟ではなく単に変更を確認するのは “SOLD OUT” ボタンタグの有無にし、混雑時のエラーページを回避する条件分岐を加えたそんなこんなで現在この様なコードで常駐しています。

property INTVAL_CHECK : 90
property INTVAL_NOTIFY : 300
property INTVAL : INTVAL_CHECK
property BASE_URL : "https://store.nintendo.co.jp/customize.html"
on idle
 try
  set rawHTML to do shell script "curl -si " & BASE_URL
  if paragraph 1 of rawHTML is "HTTP/1.1 200 OK" and rawHTML contains "カートに進む" then
   set INTVAL to INTVAL_NOTIFY
   my sendMessage("+8180********", "マイニンテンドーストアで Nintendo Switch の販売が開始されました。" & " " & BASE_URL)
   else
    set INTVAL to INTVAL_CHECK
  end if
 end try
 return INTVAL_CHECK
end idle
on sendMessage(targetBuddyPhone, targetMessage)
 tell application "Messages"
  set targetService to 1st service whose service type = iMessage
  set targetBuddy to buddy targetBuddyPhone of targetService
  send targetMessage to targetBuddy
 end tell
end sendMessage

当初 curl コマンドをオプション指定無しに利用していたところ、プログレスメータをアラートダイアログに表示するということがあり s オプションを、更に鯖落ちしていた場合に備え i オプションを付与しレスポンスヘッダが 200 の場合にのみ処理を実行する様にしました。また、メッセージアプリの宛先がメールアドレスにした場合のエラーを解決できなかったので仕方なく電話番号にしました。

自分からメッセージが送られるという特殊性を活かし、iOS のアドレス帳編集からメッセージ着信音を特別分かりやすいものにすると認知向上に尚良いかと思います。(因みにバルーンファイトのゲームオーバー音を設定しました)

最後に開発環境上で動作させることを考慮し Info.plist に <key>LSBackgroundOnly</key><true/> を追加することでドックにもアプリ切替時にもアイコンを表示させない様にしました。後は増産を待つばかり。

追記:
「0以外の状況でコマンドが終了しました。」というエラー内容(英語では “The command exited with a non-zero status”)は、シェルスクリプトの実行が失敗した際に 0 以外の数字を返した場合に発生することとその回避方法をアップルの公式文書で知りました。

http://hkitago.tumblr.com/post/162968916786

man curl を参照すると 1 から 99 までと XX を返す様で、シェルスクリプトのリダイレクトを利用すると空の値を返した際に次の行にある分岐条件が増えることが格好良く思わなかったので今回は Try ハンドラを利用しました。余談で公式文書にツッコミを入れると、リダイレクトを利用する場合は文末にアンパサンドが必要でないか、と…

追記1:
販売が開始されたら通知の間隔を大きくする目的で、2つの巡回用の数値変数を与えて条件分岐で変更できる様にしました。最初の通知を見逃すと痛手なのですが、気づいて買い物手続き中に通知だらけになるのも避けたいという難しいところ、リマインダアプリの「実行済み」ボタンの様な機能を通知持たせることができれば最善だと感じる苦肉の策。

追記2:
「文字列 “SOLD OUT” を含まない」と言う条件だとコード内でコメントアウトされていたり CSS で非表示になっていた場合に失敗することが分かったので修正。

参考:

WebViewのフォーム入力でImmersiveモードを維持する

前回、Javascript の alertconfirm 関数を使って WebView から AlertDialog を呼び出した際に全画面表示を止めてしまう問題について取り組んでいた時に、入力フィールドへフォーカスした際に Immersive モードが解除されるのは仕方がないとしても、その扱いについて考えていたところ、こちらも一癖ある挙動だったので紹介します。

通常 Immersive モードではない場合、WebView にキーボードが被るという問題を解決すべく、AndroidManifest.xml の activity ノード属性として android:windowSoftInputMode="adjustResize" と書くのですが、Immersive モードの場合はこの方法がうまくいきません。そこで試してみたのが、入力フィールドがフォーカスした時に Immersive モードを解除する、という方法です。

まず、MainActivity クラスの中に次のような JavaScript インターフェースを用意し、

public class WebViewJavaScriptInterface{
  private Context context;
  public WebViewJavaScriptInterface(Context context){
    this.context = context;
  }
  @JavascriptInterface
  public void disableFullScreen() {
    getWindow().getDecorView().setSystemUiVisibility(0);
  }
}

WebView について色々と書いてある onCreate の中で JavaScript から呼び出せるように設定しました。

webView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");

そしてテキスト入力フィールドを1つ持っている HTML ではこのように JavaScript から Immersive モードを解除するようにしました。

document.querySelector('input[type=text]').ontouchend = function(){
  app.disableFullScreen();
};

ところが、Logcat に “Uncaught Error: Java exception was raised during method invocation” というエラーを出力しうまく動かなかったので、MainActivity で Handler を呼び出し、JavaScript インターフェース内の関数を次のようにすると期待通りの動作をエミュレータで確認しました。

@JavascriptInterface
public void disableFullScreen() {
  handler.postDelayed(new Runnable() {
    @Override
    public void run() {
      getWindow().getDecorView().setSystemUiVisibility(0);
    }
  }, 0);
}

また、JavaScript インターフェース内にもう一つ次のようなものを用意して(前回不要だと思った enableImmersiveMode 関数を再度用意)、

@JavascriptInterface
public void enableFullScreen() {
  handler.postDelayed(new Runnable() {
    @Override
    public void run() {
      enableImmersiveMode();
    }
  }, 0);
}

送信ボタンを押した時に Immersive モードとなるようにしました。

document.querySelector('#submit').ontouchend = function(){
  app.enableFullScreen();
};

実際にこのような挙動で動くようになったのですが、

ソフトウェアキーボード以外の場所で画面を押すと入力フィールドからフォーカスが外れてキーボードが隠れるという OS の設計上、このように加えておくと更に安心です。

document.querySelector('input[type=text]').onblur = function(){
  app.disableFullScreen();
};

実機で検証してみると、処理能力が劣る古い機種ではフルスクリーンになる際にステータスバーが途中で止まってしまったりということが確認できたので、postDelayed で遅延を750〜1000と与えると(動作的にはギクシャクする感は否めないのですが)解決しました。そして、最初に書いていた android:windowSoftInputMode="adjustResize" を外してみると…なんと入力フィールドが隠れずにキーボードに合わせて移動するという世にも奇妙な…。

参考:

WebViewのAlertDialogでImmersiveモードを維持する

Android の上部にあるツールバーと下部にあるナビゲーションバーを隠しフルスクリーンで表示する「Immersive モード」を使ってハイブリッドアプリを開発している際に、WebView 内の JavaScript で confirm を呼び出すと、全画面表示が解除されてツールバー及びナビゲーションバーが再び表示されてしまうという問題に直面したので調べました。

元々は confirm のボタンラベル名を拡張すべく WebChromeClient 内でこのようなコードを使っていました。

@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result)  {
  new AlertDialog.Builder(MainActivity.this)
    .setMessage(message)
    .setPositiveButton("確認",
      new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
          result.confirm();
        }
      })
    .setNegativeButton("消去",
      new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
          result.cancel();
        }
      })
    .setCancelable(false).create().show();
  return true;
};

この問題の根本にある原因はダイアログがフォーカスを持ってしまうことにあるようなので、参考にした文献のコードを利用し(ワンライナーフェチとしては少し残念な) AlertDialog を一旦 alertToShow に入れるようにして addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) を追加しました。

@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result)  {
  AlertDialog alertToShow = new AlertDialog.Builder(MainActivity.this)
(中略)
  alertToShow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
  alertToShow.show();
  return true;
};

今回の失敗談を一つ紹介すると、MainActivity に次のような全画面設定関数を用意して setPositiveButtonsetNegativeButton のそれぞれの onClick で呼び出したのですが、案の定ボタンを押した後に Immersive モードを再開するという間抜けな結果になり、上述したコードで不要になりました汗。

@SuppressLint("NewApi")
private void enableImmersiveMode() {
  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
  }
}

この例は JavaScript の confirm でしたが、もちろん alert でも同じような処理で解決できると思います。更に調べているとテキストフォーム入力時の input にフォーカスした際に下部からニュッと現れるソフトキーボードと共に Immersive モードが解除されるという問題について Stackoverflow で多く議論されていることが分かりました。こちらも原因は同様なのですが WebView と連携した場合にどうなるのか、別投稿で紹介したいと思います。

参考:

MySQL 5.7のLaunch Daemonを使う

Sierra に更新し前投稿の問題以降に再起動をすると、ERROR! The server quit without updating PID file というエラーを出力し MySQL が起動しなくなるという新たな問題が解決しなかったため、MySQL 自体の更新も兼ねて MySQL 5.7をクリーンインストールしました。そこでマニュアルを参照してみると、意外にも MySQL の起動にコントロールパネルの利用を推奨していたので試してみたところ、またまたうまく機能しなかったので少し調べてみました。

その結果、MySQL 5.6 を Yosemite にインストールした時は、起動アイテムを使っていた公式のコントロールパネルが機能せず、別途起動デーモンを書いていた(まさかの公式マニュアルに掲載)のですが、MySQL 5.7 のインストーラは独自の起動デーモン com.oracle.oss.mysql.mysqld.plist/Library/LaunchDaemons/ に配置するそうなので、前バージョンからの移行で 5.7 を利用する場合は com.mysql.mysql.plist を削除する必要がある、という簡単な解決方法でした。

ただ、前バージョンに引き続きコントロールパネルを利用しないという方法も可能なので、その場合は上述のように com.mysql.mysql.plist を削除することなく、コンパネやコマンドを使って公式の com.oracle.oss.mysql.mysqld.plist を読み込まないように、ファイルの場所を代えるなど注意をする必要があります。

参考:

Please DISCARD the tablespace before IMPORT エラー対処

MacOS Sierra 移行前の話なのですが、innoDB を扱う案件があり開発環境で設定してみたところ、phpMyAdmin 4.6 上でテーブル名は見えているのだけど「テーブルがありません」というエラーを返してきたので、で該当テーブルを削除した後に再度同じ名前でテーブルを作ろうとすると今度は、”Please DISCARD the tablespace before IMPORT” というエラーを返してきて、二進も三進もいかなくなったということがありました。

そこで例によっておググりなさってみると、/usr/local/mysql/data にある問題となっている DB 名のファイルを消去する方法を見つけたので試してみたところうまくいかなかったので、MySQL の起動を停止し他のファイルを消すか名称変更しつつ再度 MySQL を起動する、という手順を繰り返しディレクトリ内を観察してみた結果、[PC_Name].local.err や [PC_Name].local.pid も関係することが判明し、元々開発環境でデータの消失は問題がないということもあり、次のように MySQL が起動時に参照したり生成するファイルも削除してみたところ、無事テーブル生成が可能になりました。

$ cd /usr/local/mysql/data
$ sudo launchctl unload -F /Library/LaunchDaemons/com.mysql.mysql.plist
$ sudo rm -rf [問題のDB名]
$ sudo rm -rf ib_logfile0
$ sudo rm -rf ib_logfile1
$ sudo rm -rf ibdata1
$ sudo rm -rf [PC_Name].local.err
$ sudo rm -rf [PC_Name].local.pid
$ sudo rm -rf phpmyadmin/
$ sudo launchctl load -F /Library/LaunchDaemons/com.mysql.mysql.plist

もちろんこの後で再び phpMyAdmin を利用するには phpmyadmin/sql/create_tables.sql をインポートし再設定する必要があります。

参考:

photoanalysisdプロセスの挙動

MacOS Sierra に更新してアクティビティモニタを見てみると photoanalysisd というプロセスが常時100%超えを示していて、丁度重い作業をするところだったのでリソース不足を解消するために次のような launchctl コマンドを使って一旦止めることしました。

http://hkitago.tumblr.com/post/151969879196

作業も終わったところでさてこのプロセスは何をしているのかと、アクティビティモニタのプロセスを開いて「開いているファイルとポート」タブからログを眺めていると、写真アプリのライブラリ内データを読んでいることが分かりました。

更に “~/Library/Application Support/AddressBook/…” というログを見つけたので、写真アプリのアルバム>ピープルを見るとこのようなメッセージを表示していました。
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-19-6-40-18

実際に写真アプリを起動すると photoanalysisd プロセスの CPU 使用率は0%になり、閉じると再び上昇するという挙動をしていましたので、作業中は上述したコマンドでプロセスを終了し、夜間など使用しない際に再度プロセスを読み直すという方法が良いのかと思います。

夜間に放置しておいたところ、約4万2千枚ある写真のライブラリを12時間くらいかけて解析していました。
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-19-8-19-33

参考:

Macで再生する音を録音する

Mac の QuickTime Player 10 を使い、ブラウザで表示するストリーム配信の番組を(私的利用を目的として)画面収録したり、携帯の着信音を作るのに録画機能の無いゲームエミュレータの音を(こちらもくどいけれども、私的利用を目的として)オーディオ収録する場合は Soundflower をインストールして使うのだけど、久しぶりにやろうとして設定をググった挙句に日本語のブログを漁るとどれも「録音中に音は鳴りません」と書いてあるものだから仕方なく過去のタンブラ投稿を探して、正しくモニタリングしながら録音する方法がグーグル検索の上位になるように投稿します。

http://hkitago.tumblr.com/post/102015637138

作業環境は、OS X El Capitan バージョン 10.11.6、Soundflower 2.0b2、Audio MIDI 設定 バージョン 3.0.6 を使いますが、上記に引用したのは2年程前でしたし、OS X のオーディオ設定周りはあまり変わらないので OS X のバージョンに対応する Soundflower がインストールされていればあまり気にする必要はないと思います。そこでこの引用をさっと訳すと、

  1. Soundflower をインストールします。
  2. Audio MIDI 設定.app を開き、ウィンドウ左下にある(+)ボタンを押し、「複数出力装置を作成」を選びます。
  3. 左側のアイコンが並ぶ装置一覧に「複数出力装置」が追加されるので、アイコン左横にある三角矢印を押し、「内臓出力」「Soundflower (2ch)」「Soundflower (64ch)」が含まれていることを確認します。
    スクリーンショット 2016-08-26 15.47.57
  4. QuickTime を開き、メニューバーから「ファイル>新規画面収録」コマンドを選びます。(音だけの場合はもちろん「新規オーディオ収録」で可)赤い録画ボタン右横にある下矢印ボタンを押し、「Soundflower (2ch)」あるいは「Soundflower (64ch)」を選びます。
    スクリーンショット 2016-08-26 16.03.26
  5. 以上で収録を始めると、音を聞きながら録音、録画することができます。

となるのですが、実はこのままでは録画、あるいは録音したファイルに音データが含まれないという失敗になるので、多くの日本語記事にもあるように出力先を変更する必要があります。但し、今回の設定環境では出力先を 2ch や 64ch ではなく、「複数出力装置」とする必要があります。もちろん環境設定を開くという手間を省いて、オプションキーを押しながらメニューバー右上のスピーカーアイコンを押すと簡単に出力先の設定ができます。
スクリーンショット 2016-08-26 16.09.27

更に出力先を「複数出力装置」に変更した場合、キーボードの音量設定ボタンが無効になってしまうので、調整は Audio MIDI 設定.app で行います。「複数出力装置」に含まれる「内臓出力」を選択し、右側に表示される両チャンネルのスライダを変更することでも良いですし、収録前にスライダを設定しておきつつ、モニタ中に煩くなったら下図のようにマスタの消音チェックボックスを入れるという方法も可能です。
スクリーンショット 2016-08-26 16.20.15

最後に注意点としては QuickTime で収録ボタンを押す前に、その下部にある音量スライダが左端にあって音声出力しないようになっていることを確認する必要があります。もしスライダが右方向にあって収録を始めるとハウリングの嵐に巻き込まれて…(略 そんな時は慌てずメニューバーにある収録中止ボタンをしましょう笑)

iPhone5sをアンロックする

受託案件が増えたのでアンドロイド端末を一台持たねばと購入した HUAWEI P8lite だったのですが、イングレスで使うには GPS がブレたり大きな画面でグリフハックがやり辛いことなどから、開発用途としてソフトバンク契約が切れて Wi-Fi のみで利用していた iPhone5s をアンロックして DMM の SIM を使ってみようと思いました。今回はジェイルブレイク(脱獄)せず、SIM アダプター(下駄)も使わず、単純に IMEI アンロック(ファクトリーアンロック)をすることを目的としています。

まず “iphone unlock softbank” 程度の検索語で出てきたサイトですが、格安だったのでサイト名に “scam” キーワードを付けてみたところ見事に詐欺サイトだと判明しました。Fb ではかなりの評判だったのがあわや騙されるところで、体験談を読むと明示されている19ユーロというのは前金で、これを支払った後に60ユーロの請求が届き、更にこれを支払った後に音沙汰がなかったり、未だ時間が掛かると自動返信でトンズラするそうです。(具体的には英国のオフィシャルアイポンXXXXXXユーケーというサービスです、ご注意ください)

次に MacRumors のフォーラム経由で見つけたのが、UnlockBase という米国のサービスで、複数の情報源から信頼できると判断しこちらを利用することにしました。実際に申し込む前に確認すべきことは次の3つです。

  • IMEI 番号の確認:
    電話アプリのキーパッドで *#06# と押し、メモアプリなどに控えておきます。設定>一般>情報>IMEI からだと番号を長押しでコピペできます。
  • アップルのサイトでアクティベーションロックの状態を確認
    対象機種の「iPhone を探す」機能がオフになっているかどうかを確認できます。
  • IMEI Database Lookup で iPhone のシムロックの確認
    キャリアとの契約状態や盗難品かどうかを確認できます。

理想的なのは国内のキャリアで購入し契約の切れた iPhone があると良いのですが、秋葉原やヤフオクなどで中古端末を入手している場合は少し注意が必要です。これらの確認が終わったら、UnlockBase のトップページ上部に見える iPhone の GET STARTED からメーカーと機種を選択し “UNLOCK NOW” ボタンを押して進みます。次のページでは、IMEI 番号、メールアドレスを入力し、国名、契約中のキャリア名を選び “PROCEED TO CHECKOUT NOW” ボタンを押して支払い方法を選びます。今回は Paypal を選択し、待つこと13営業日で無事に作業が完了したという旨のメールを受け取りました。早速メールにリンク先のある “How to Unlock the Apple iPhone 5S” を読み(緊急通話のみのソフトバンク SIM を使い USB を経由し iTunes で認識させてから抜き、10秒待ってから再接続再認識させるだけ) DMM のプロファイルをダウンロードし SIM を交換してみたところ見事に「ドコモ 24.2」のキャリアを掴みました。

またこの待ち時間を利用して内臓バッテリーの交換を試みました。

手順は若干多様性があるようでしたが、iFixit を主な参考にしてパネルを外さない方法を選択しました。バッテリ自体は強力な糊付けだったのですが、AirMac の底面などで分解経験のあるヘアドライヤで外しました。
IMG_0816

最初に届いたものは充電ができない不良品でしたが、返品して再度購入し無事新品のような状態になりました。

IMG_2492

電池交換後に計測に使用していたアプリを一旦削除しないと測定値をリセットしないという問題も発見しました(この間にサイクルが1増えてた笑)が、無料なので開発側には報告しませんでした。

IMG_2507

ということで、中古の端末が多く流通しているということや円高傾向もあり、SE の購入に悩んでいたり(Android 端末のアンロックも可能らしい)、月額の出費を抑えるのに格安 SIM に移行したい、夏休みに向けて子供の GPS トラッキング用途、サブ機などにいかがでしょうか。

参考:

Windows 10への更新を避ける

最近話題なので…。
Parallels Picture のコピー

開発環境上で Windows は XP、7、10という複数のバージョンを Parallels で仮想化し利用していることもあって勝手に更新されては困るということから回避方法を探していました。

スクリーンショット 2016-06-02 9.05.51
レジストリエディタでゴニョゴニョする等、幾つかのやり方を眺めた中で、次のようなウィンドウズアップデートコントロールパネルに表示させないという方法が簡単にうまくいったので紹介します。


まず「コントロールパネル>プログラム>プログラムのアンインストール>インストールされた更新プログラムを表示」と進み(一覧全てを表示するのには少し時間が掛かるかもなので上部のプログレスバーに注目)Windows 8.1 の場合は、「KB3035583」と「KB2976978」と名前に書かれてある更新プログラムを、Windows 7 の場合は、「KB3035583」、「KB2952664」そして 「KB3021917」と名前に書かれてある更新プログラムを探し、それぞれの項目の上で右クリックし「アンインストール」します。その都度再起動を促されますが、全ての作業が終わるまで再起動は後回しにし、全てアンインストールが終わったら再起動します。

再起動が終わったら「全てのプログラム>Windows Update>更新プログラムの確認」と進みます。すると先ほどアンインストールした更新プログラムとウィンドウズ 10 への更新プログラムが再び現れるので、それぞれの項目上で右クリックし全て隠し通知しないようにします。(隠すと文字の色が薄い灰色に変わります)

Parallels Picture 1

最後にこの記事の中では、既に更新ファイルがローカルディスクにダウンロードされているかどうかを確認し、あれば削除するようにしています。ファイルエクスプローラーのフォルダオプションで不可視ファイルを表示するようチェックボックスを入れて C ドライブの最上位階層に “$Windows.~BT” という3〜6 GB のフォルダが該当するのですが、こちらの環境では見当たらず実行する必要がありませんでした。

参考:

Safari 9.1.1でAppleScriptからJavaScriptを実行する

以前、Ingress のプレイ記録用途に AppleScript を書いたのだけど、半径3キロメートルに及ぶノバ作戦を近所で開催した時にもっと大きなインテルマップを表示しようと、次のようなコードを追加していました。

on fullScreenIntelMap()
	tell application "/Applications/Safari.app"
		tell document 1
			do JavaScript "document.getElementById('dashboard_container').style.left='0';document.getElementById('dashboard_container').style.top='0';document.getElementById('dashboard_container').style.right='0';document.getElementById('dashboard_container').style.bottom='0';document.getElementById('comm').style.display='none';document.getElementById('player_stats').style.display='none';document.getElementById('rs_box').style.display='none';"
		end tell
	end tell
end fullScreenIntelMap

この関数を起動時の on run と再読み込み時の on idle で実行すると、ヘッダ部分やフッタ部分を隠しブラウザのフルスクリーンモードにして可能な限り広域な地図状況を記録しておくことができるのですが、最近になってこのスクリプトを使うと Safari が次のようなエラーを返してきました。
スクリーンショット 2016-06-01 9.03.48

You must enable the ‘Allow JavaScript from Apple Events’ option in Safari’s Develop menu to use ‘do JavaScript’.

この内容に従って「開発」メニューを覗いてみると次のように「Apple Events からの JavaScript を許可」というコマンドがありました。

スクリーンショット 2016-06-01 9.04.24
この見慣れぬコマンドについて確認しようと Apple のサポートページを見ると未だ記述がないので、どうやら最新のバージョン 9.1.1 から追加されたものと思われます。そこでもう少しおググりなさってみると、数日前に “do JavaScript 記述のある AppleScript が動かなくなったよ〜” という内容で、とあるマックサイトのフォーラムに投稿している人がいました。

その内容によると、どうやら Safari の「開発」メニューを表示しておかないと上述したようなエラー内容を表示せず、コンソールに不可解なエラーメッセージだけが残るそうなので注意が必要です。

http://hkitago.tumblr.com/post/145244516611

確かに近年 JavaScript の台頭と安全性について語られることが増えていますが、わざわざ開発メニューから設定する必要があるのは柔軟性という点で開発者にとってはなかなか厳しい変更点なのではないかと思いました。またこのフォーラムでも懸念されていますが、Safari 以外で AppleScript と連携ができる(特にウェブ開発で使うような)アプリケーションの対応についても今後の動向に少し注目しておく必要がありそうです。

参考: