QuickJSやDelphiに関するちょっとした雑談
-
編集モードで折り返し時、3行目から意図した色にならない で「QuickJS」について触れましたが、だいぶトピック外な話題になってしまいそうでしたのでこちらへ避難しました。雑談ちっくなスレにさせてもらえればと思っていますので、お暇なときにでも見ていただければと。
前回、Delphiで外部ライブラリを使うには~といった話が出ましたが、どうにも私の経験が無いことから「Delphiって、どうやってdllを使ったりするものなんだろう?」というのが想像つかず…もうこうなったらDelphi入門してみるかと Delphi 12 Community Edition をインストール。まずはとてつもなくシンプルなフォームでHello Worldするだけで四苦八苦しております…w Javaからプログラミングを始めたものですから、どうにも構文の違いに慣れず、まずは雰囲気を味わうところからじっくりとやらねばですね。
Delphiの話とは逸れてしまいますが、
> では、自分でビルドしようと思ったら、ビルド方法が難しすぎて詰みました🤷♂️
とのことだったので、生成AIに助けてもらいながらビルドを試してみました。
とりあえずQuickJSをdll化したものをC言語のサンプルコードでロードしてJavaScriptを実行、処理結果を受け取るところまでを確認できました。…が、C言語も分からなければMakefileも書いたことがないので変な落とし穴にハマってないだろうかと心配ではあります…😅
さて、ビルド手順は以下の通りです。
(1) MSYS2をインストールする。
MSYS2(2) MSYS2 (bash) を起動し、以下の流れでビルドする。
# MinGW-w64 (GCCとmake) をインストールする。 pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-make # QuickJSのソースコードをダウンロードして展開 wget https://bellard.org/quickjs/quickjs-2024-01-13.tar.xz tar xvf quickjs-2024-01-13.tar.xz cd quickjs-2024-01-13/ # QuickJSの静的ライブラリ (libquickjs.a) をビルドする。 mingw32-make.exe libquickjs.a # 共有ライブラリ libquickjs.dll を生成する。 gcc -shared -o libquickjs.dll -static -s -Wl,--whole-archive libquickjs.a -lm -Wl,--no-whole-archive # サンプルコード用のディレクトリを作成し、必要ファイルをコピーする mkdir sample_code cp libquickjs.* sample_code cp quickjs.h sample_code cd sample_code # サンプルコードを作成 ※コード内容は後述 touch main.c # サンプルコードをコンパイル gcc -o quickjs_example main.c -L. -lquickjs # 作成した実行ファイルを実行する。 ./quickjs_example.exe # 上記実行ファイルで、以下のような実行結果が出力されました # JavaScript result: 84main.c の中身:
#include <stdio.h> #include <windows.h> #include "quickjs.h" typedef JSRuntime* (*JS_NewRuntimeFunc)(); typedef JSContext* (*JS_NewContextFunc)(JSRuntime*); typedef void (*JS_FreeRuntimeFunc)(JSRuntime*); typedef void (*JS_FreeContextFunc)(JSContext*); typedef JSValue (*JS_EvalFunc)(JSContext*, const char*, size_t, const char*, int); int main() { // DLLのロード HINSTANCE hinstLib = LoadLibrary(TEXT("libquickjs.dll")); // DLLのパスを指定 if (hinstLib == NULL) { printf("Failed to load QuickJS DLL.\n"); return 1; } // 関数ポインタの取得 JS_NewRuntimeFunc JS_NewRuntime = (JS_NewRuntimeFunc)GetProcAddress(hinstLib, "JS_NewRuntime"); JS_NewContextFunc JS_NewContext = (JS_NewContextFunc)GetProcAddress(hinstLib, "JS_NewContext"); JS_FreeRuntimeFunc JS_FreeRuntime = (JS_FreeRuntimeFunc)GetProcAddress(hinstLib, "JS_FreeRuntime"); JS_FreeContextFunc JS_FreeContext = (JS_FreeContextFunc)GetProcAddress(hinstLib, "JS_FreeContext"); JS_EvalFunc JS_Eval = (JS_EvalFunc)GetProcAddress(hinstLib, "JS_Eval"); if (!JS_NewRuntime || !JS_NewContext || !JS_FreeRuntime || !JS_FreeContext || !JS_Eval) { printf("Failed to get function addresses from QuickJS DLL.\n"); if (!JS_NewRuntime) printf("JS_NewRuntime\n"); if (!JS_NewContext) printf("JS_NewContext\n"); if (!JS_FreeRuntime) printf("JS_FreeRuntime\n"); if (!JS_FreeContext) printf("JS_FreeContext\n"); if (!JS_Eval) printf("JS_Eval\n"); FreeLibrary(hinstLib); return 1; } // QuickJSランタイムとコンテキストの作成 JSRuntime *runtime = JS_NewRuntime(); if (!runtime) { printf("Failed to create QuickJS runtime.\n"); FreeLibrary(hinstLib); return 1; } JSContext *ctx = JS_NewContext(runtime); if (!ctx) { printf("Failed to create QuickJS context.\n"); JS_FreeRuntime(runtime); FreeLibrary(hinstLib); return 1; } // JavaScriptコードの評価 const char *js_code = "const x = 42; x * 2;"; JSValue result = JS_Eval(ctx, js_code, strlen(js_code), "<input>", JS_EVAL_TYPE_GLOBAL); if (JS_IsException(result)) { printf("JavaScript evaluation failed.\n"); } else { int32_t int_result; if (JS_ToInt32(ctx, &int_result, result) == 0) { printf("JavaScript result: %d\n", int_result); } else { printf("Failed to convert result to integer.\n"); } } // リソースの解放 JS_FreeContext(ctx); JS_FreeRuntime(runtime); FreeLibrary(hinstLib); return 0; }| yuko | 返信 -
今、最新にアップデートしたMSYS2、Cygwinと同期したコードを一部直しそびれたのか、どこか壊れてるっぽい。
$ uname -o
Msys
$ echo $OSTYPE
cygwin正しくは$OSTYPEでmsysを返すはず。
.bash_aliasesでWSL2と場合分けしている部分が誤判定して気が付いた。| enaka | 返信 -
>> yuko さん
トピック作成、ありがとうございます!まさかの Delphi デビュー、おめでとうございます😊
Delphi の構文って、C や Java に慣れてるとちょっとクセがあるように感じるかもしれませんね。でも、Pascal って昔は教育用にもよく使われてたし、意外とシンプルでわかりやすいんですよ。
あと、Delphi は Visual Studio なんかと比べるとコンパイルが速いのもいいところですね。(とはいえ、最近の Delphi は余計な機能が増えて、ちょっと重くなってますが…w)
ビルド手順の情報、ありがとうございます!
私のほうは、できれば Visual Studio でビルドしたかったので、そっちばかり調べていたのですが、なんとかビルドまではいけたものの、QuickJS のソースをいじらないとダメっぽくて、結局、最新の QuickJS には対応できずに撃沈しました…😇
pacmanって出てきたとき、「あ、これ Linux 環境じゃないと無理なやつ…?」と思ったのですが、MSYS2 という便利なものがあるんですね。いただいた手順でビルドから DLL 化までうまくいきました。
出来上がった DLL がランタイムなしで Windows でちゃんと動くのか不安だったのですが、とりあえず Windows 11 と Windows XP で試してみたら、なんとか動いてるっぽいです。
Delphi で DLL を読み込んでスクリプトを動かし、さらに Delphi 側のメソッドを JS から呼び出すところまではいけました。(まだ謎の例外が出たりしてますが)
ただ、QuickJS は ActiveScripting で使われる COM (IDispatch) 方式じゃないので、Mery のマクロ機能 (JScript9、V8 など) とは共存できず、マクロの実装を全部ゼロから作り直しですね…
JScript の廃止が決まったら、もうやるしかなさそうですが、やるとしたら、これはもう 1 年ぐらいかけての長期戦になりそうですね😱
>> enaka さん
> Delphiは、2025/02/14で発売30周年だそうですね。あと三日。
わぁ、30周年!もうそんなに経つんですね。ほんとだ、イベントもやってて盛り上がってるみたいですね。
でも、Delphi 12 Professional、キャンペーン価格でも17万円…。定価だと20万円にもなるんですね。(;^ω^)
> Delphiに組み込んで使うスクリプト言語だと、ゲームエンジンなんかに使われて知られている、Luaが実績豊富ですね。
私も Lua はゲーム作りで使ったことがあるのですが、シンプルで分かりやすくていいですよね!
実はそのとき、Lua にすっかりハマっちゃって、遊びで Mery に組み込んでみようかななんて調べてたこともあったんです。
でも、Delphi の Lua ライブラリって本当にたくさんあって、どれを選ぶかだけでも結構迷いそうですよね。
> ちょっと裏が取れないんですが、embarcadero公式の中の人によるとJavascriptsの場合、Delphi内部の実装との兼ね合いで型推論が使えなくなっちゃうんだとか。
そうなんですね。Mery の開発環境は Delphi XE2 なので、そもそも型推論が使えないから、あまり影響はなさそうですが…
Lua は面白そうですが、Mery のためにわざわざ Lua を覚える人は少ないかなぁというのが懸念点ですね。
JavaScript なら Mery だけじゃなくて、他にもいろいろ活用できるので、ユーザー側からすると習得しやすいところがポイント高いのかなと思ったりしています。
でも、Lua も候補として参考にさせていただきますね。
| Kuro | 返信 -
> Delphi の構文って、C や Java に慣れてるとちょっとクセがあるように感じるかもしれませんね。でも、Pascal って昔は教育用にもよく使われてたし、意外とシンプルでわかりやすいんですよ。
Pascal? Delphi? はてどんな関係が…🤔 と思って調べたら、Pascalって言語をベースにWindowsアプリ開発向けに発展させたのがDelphiなんですね。
調べていて、たしかに教育を想定してPascalが作られたという話も見かけたので、分かりやすさに注力されていそうな印象ですね。新しい言語は久しぶりなので、ちょっと楽しみです。
実用できるアプリケーションをイチから作る体力とアイデアは無いので、やっぱりMeryプラグインとか作ってみたいところ。今まで作ってみたいと思いつつも、ずっと腰が重くて着手できなかったのですよね。まぁ、Meryプラグインでもなにかアイデアがあるわけではないんですが…😅
>
pacmanって出てきたとき、「あ、これ Linux 環境じゃないと無理なやつ…?」と思ったのですが、MSYS2 という便利なものがあるんですね。何となく後発型Cygwinって感じなんですが、Git for Windowsに付属するBashやWSLが出てくる前はよく使っていました。
Windowsのパス変換もうまく働いてくれて便利で、エクスプローラーからドラッグ&ドラッグすると勝手に変換が掛かりますね。あとは
~/.bashrcにalias mery="/c/<path>/Mery.exe"を書いておいて、MSYS2上からmery hoge.txtみたいにパスを渡して実行してもちゃんとWindowsパスに変換してくれたりもします。> 出来上がった DLL がランタイムなしで Windows でちゃんと動くのか不安だったのですが、とりあえず Windows 11 と Windows XP で試してみたら、なんとか動いてるっぽいです。
> Delphi で DLL を読み込んでスクリプトを動かし、さらに Delphi 側のメソッドを JS から呼び出すところまではいけました。(まだ謎の例外が出たりしてますが)おおー、軽い気持ちで紹介してみましたが、意外と幸先良い感じ…!?
もしMeryでも動かすことができたなら、JScript、V8と比べてパフォーマンス (起動時リードタイムと、重い処理をしたときの全体速度) がどれほどのものなのかが気になります!> ただ、QuickJS は ActiveScripting で使われる COM (IDispatch) 方式じゃないので、Mery のマクロ機能 (JScript9、V8 など) とは共存できず、マクロの実装を全部ゼロから作り直しですね…
> JScript の廃止が決まったら、もうやるしかなさそうですが、やるとしたら、これはもう 1 年ぐらいかけての長期戦になりそうですね😱#language指定で変えたり、それが難しければ隠しオプションでマクロエンジンを切り替えられるようになると、テストのために切り替えて使うこともできるので良さそうですね。そのときは喜んで試用させていただきたいと思います。自分で言うのもなんですが、Meryユーザーの中でも結構なマクロ利用者だと思うので、テスターとしては最適かと…wいずれこの取り組みが実を結んで、重量級なV8を使わずにES2023仕様に対応する日本語テキストエディタとなったら、国内初な事例になりそうですよね。
| yuko | 返信 -
> Pascal? Delphi? はてどんな関係が…🤔
すみません、完全に脳内で Pascal = Delphi になっちゃってて、ついポロっと出ちゃいました😅
> 実用できるアプリケーションをイチから作る体力とアイデアは無いので、やっぱりMeryプラグインとか作ってみたいところ。
プラグインなら Windows API を直接叩けるので、マクロよりも Windows でできることなら何でもできる感じですね。
ただ、マクロは今までヘビーユーザーさんのおかげで成長してきましたが、プラグインのほうは Mery 間通信の面で、ちょっと置いてけぼり感がありますね。
> 何となく後発型Cygwinって感じなんですが、Git for Windowsに付属するBashやWSLが出てくる前はよく使っていました。
ほほー、私、Cygwin はサッパリで、その辺りはまったく触れたことないんですよね。WSL は以前、Mery の案件でちょろっといじったのですが、結局そっと削除しました…
> おおー、軽い気持ちで紹介してみましたが、意外と幸先良い感じ…!?
そうですねー、今のところ好感触です。作業量を考えるとアレですが、技術的には時間をかければなんとかなるかも、という感じはありますね😅
> もしMeryでも動かすことができたなら、JScript、V8と比べてパフォーマンス (起動時リードタイムと、重い処理をしたときの全体速度) がどれほどのものなのかが気になります!
そこまで実装したあとに「やっぱり遅かったですわー」ってオチは避けたいですが、作者様も「めっちゃ速いよ!」って言ってますしね。
【参考】QuickJS ベンチマーク
https://bellard.org/quickjs/bench.htmlちなみに、今の時点でテストアプリの起動時リードタイムは、Delphi から DLL を使ってもほぼゼロです。
Mery 側のオブジェクトやメソッドを注入するとなると初期化で多少時間がかかるかもですが、V8 (裏で Edge が起動するレベル) みたいなことにはならないと思います。
> #language 指定で変えたり、それが難しければ隠しオプションでマクロエンジンを切り替えられるようになると、テストのために切り替えて使うこともできるので良さそうですね。
そうですね。現行のマクロの実装を残したまま、別系統で新たなマクロ機能を追加する感じになるので、ちょっとヤな感じですけどね。
(まあ、それを言うと鬼雲/鬼車も同じ仕組みで実装してるし、RegExMode=2 も同じですけどw 試験的な実装なので、最終的にはどちらか廃止の方向ですね)
> 自分で言うのもなんですが、Meryユーザーの中でも結構なマクロ利用者だと思うので、テスターとしては最適かと…w
あはは、システム屋さんには「言い出しっぺの法則」というものがありますからね!そこはがっつりおなしゃすw (冗談です)
> いずれこの取り組みが実を結んで、重量級なV8を使わずにES2023仕様に対応する日本語テキストエディタとなったら、国内初な事例になりそうですよね。
そうですね。V8 も「重量級」というわけではなくて、Mery の実装が WebView2 経由だから重くなってる感じなのはあるかもですが。
あとは、QuickJS の将来性がちょっと気になるところで、メンテされなくなったらそれで終わりですし、最後のリリースが 1 年前。
ユニコード対応も 15.0 で止まってるので、今後の動向を見守りたいですね。
理想的には WebView2 なしで V8 を直接使えるのがベストですが、ActiveScript 廃止の流れで Microsoft から何か救済措置が出てこないかしら…😒
| Kuro | 返信 -
> 理想的には WebView2 なしで V8 を直接使えるのがベストですが、ActiveScript 廃止の流れで Microsoft から何か救済措置が出てこないかしら…😒
たまたま見かけたので初カキコ。
https://github.com/microsoft/ClearScript
Microsoft公式だと.Netアプリ向けライブラリのClearScriptがV8(とJScriptとVBScript)を使えますね。
Meryに使えるかは分からないですけど。| barrackdo | 返信 -
Meryでのプラグイン開発は、 haijinboys/mery-plugin-sdk: Plugin SDK for Mery あたりから見ていくのがスムーズでしょうかね?もし他にも「このへんの情報が参考になるよ」といったものがあれば教えていただけると嬉しいです🙇
> 作業量を考えるとアレですが、技術的には時間をかければなんとかなるかも、という感じはありますね😅
ですよね…😅 それを考えるとなかなか推しづらいですが、でも導入されたら嬉しいなとやっぱり期待しちゃいます。
ES6以降でしか使えない文法や関数なんかを横目に見つつ、がんばってJScript (ES5) 仕様で書いた瞬間は何度もあったので、手軽に新しいJavaScript文法が使えるようになると嬉しいんですよね。JavaScript駆け出しでマクロを書いていた頃は、検索して出てくるブログが軒並みES6以降前提だったりして、それでいてJavaScriptにバージョンなんてものがあるとも知らなかったので、幾度とコケ続けたものです……(遠い目)
> ちなみに、今の時点でテストアプリの起動時リードタイムは、Delphi から DLL を使ってもほぼゼロです。
おー、すごい!ffmpegの作者様、さすが伊達じゃありませんね。
> あはは、システム屋さんには「言い出しっぺの法則」というものがありますからね!そこはがっつりおなしゃすw (冗談です)
その際には、しっかり言い出しっぺの責任 (というほど重くも捉えてないですがw) を果たしたいと思います😉
> そうですね。V8 も「重量級」というわけではなくて、Mery の実装が WebView2 経由だから重くなってる感じなのはあるかもですが。
WebView2の立ち上がりが遅い、みたいな感じなんでしょうかね。まぁV8本体の実行ファイルサイズもなかなからしいので、それも相まってなところがあるのかもしれませんね。
> あとは、QuickJS の将来性がちょっと気になるところで、メンテされなくなったらそれで終わりですし、最後のリリースが 1 年前。
> ユニコード対応も 15.0 で止まってるので、今後の動向を見守りたいですね。どうやら、まさしくKuroさんと同じ懸念を開発者コミュニティでも持っていたらしく、「QuickJS-NG」というフォークプロジェクトが発足していたようです。
- GitHubリポジトリ: quickjs-ng/quickjs: QuickJS, the Next Generation: a mighty JavaScript engine
- ドキュメントページ: QuickJS-NG
Differences with bellard/quickjs によると、QuickJSからの乗り換えを想定していると謳っていますね。「テストに力を入れている」とも書かれており、どうやらCI (自動テスト・自動ビルド) も導入されていてモダナイゼーションに余念がない様子…。
ざっとドキュメントやリポジトリの状態を眺めたところ、活発にメンテされているようです。
- GitHubスター数が1000を超える
- こういったライブラリ系リポジトリで1000を超えてくると、かなり人気なんだなぁという印象を受けます
- コントリビューター (同リポジトリにコミットをしたことがある人) が50人を超える
- 2ヶ月程度で新バージョンをリリース
- Releases · quickjs-ng/quickjs を見ると、Unicode 16には v0.7.0 で対応済みなようです
- クロスプラットフォーム対応を謳っており、 Supported Platforms を見ると確かにVisual Studio 2022以降対応らしい表記が。
| yuko | 返信 -
>でも、Pascal って昔は教育用にもよく使われてたし、意外とシンプルでわかりやすいんですよ。
Pascalを55年前に開発したヴィルト先生、去年の最初に亡くなられたばかりで生涯現役でした。
オリジナルのPascalはアルゴリズム研究で生み出された言語で、画面やキーボードはおろか入出力の機能を一切持っていません。弟子のカーンがヘルスバーグに依頼し入出力機能を追加してパソコンで動くようにしたのがボーランドのTurboPascal。
AppleがMac用としてPascalにオブジェクト指向の独自拡張したのがObjectPascalで(やがて捨てられ)、それに対抗してヘルスバーグがオブジェクト指向の拡張をしたのがDelphiです。Delphiのオブジェクト指向は、ヴィルト先生がPascalの後にOS研究のために作ったModula-2言語の影響を強く受けていて、ObjectPascalと言えば現在ではこちらを指します。
ボーランドを追放されたのち、カーンはカメラ付携帯電話を発明し、ヘルスバーグはMicrosoftでJ++とC# の開発をしたとか。>でも、Delphi 12 Professional、キャンペーン価格でも17万円…。定価だと20万円にもなるんですね。(;^ω^)
開発者5人以下&年間売り上げ千ドルまでは無料版の Community Editionが使えますから(笑)
以前は、Professionalのメジャーバージョンが上がると、旧版の最終版が Community Editionとして期間限定ライセンスでリリースされていました。今現在、Professionalのリリースが遅れてCommunity Editionのライセンス期限が来てしまったため、Professionalと同じ12がCommunity Editionとしてリリースされたそうです。
リリース遅れには新型コロナの影響があったんでしょうね。他にオープンソースのFreePascalを用いた、オープンソースのLazarusというDelphi互換の開発環境があるようです。
>Mery の開発環境は Delphi XE2 なので、そもそも型推論が使えないから、あまり影響はなさそうですが…
誤解を生む書き方ですいません。組み込んだJavascriptでは型推論が使えなくなるようです。
| enaka | 返信 -
>> barrackdo さん
情報ありがとうございます。
ClearScript、初めて知りましたが、すごいですね、これ!
.NET アプリ向けなので、Mery では使えないのがちょっと残念ですが… Microsoft さん、Win32 アプリ向けの ClearScript も作ってくれたら嬉しいなぁ。
>> yuko さん
> Meryでのプラグイン開発は、 haijinboys/mery-plugin-sdk: Plugin SDK for Mery あたりから見ていくのがスムーズでしょうかね?
そうですね、SDK に簡単なサンプルも入ってるので、Mery にプラグインを組み込むところまでは割とスムーズにできると思いますよ。
ただ、API の詳細な仕様書がないので、ヘッダーファイル (mPlugin.pas) を読みながら推測していく感じになりますね。
C++ 用のヘッダーファイル (plugin.h) もあるので、Delphi の書き方で迷ったときはそっちと見比べてみると、ヒントになるかもしれません。
> ですよね…😅 それを考えるとなかなか推しづらいですが、でも導入されたら嬉しいなとやっぱり期待しちゃいます。
確かに、ES2023 の構文が Mery で使えたら楽しそうですね!私も試してみたい気持ちはめっちゃあります😊
> どうやら、まさしくKuroさんと同じ懸念を開発者コミュニティでも持っていたらしく、「QuickJS-NG」というフォークプロジェクトが発足していたようです。
情報ありがとうございます。
おおー!QuickJS について調べたときにはまったくヒットしなかったのですが、このプロジェクトは面白いですね。
任天堂スイッチの自作アプリのフレームワークでも使われているとか、テンション上がりますね。
早速試してみたところ、Visual Studio で DLL をビルドできて、Delphi からも使えました。
本家の QuickJS とは若干互換性が損なわれているようですが…
今のところ quickjs.h の関数 20 個ぐらいを Delphi に書き直したところですが、一応シンプルなコードなら動いてます。
quickjs.h は 1000 行ぐらいあるので、ここからは気合いと根性でコツコツ Delphi に翻訳するしかなさそうですね。
あと、気になった点をメモしておきます。
- スクリプトのエラーメッセージが英語のみ
- しかも、ソースコードに直書きされてるので、ローカライズは難しそう
- HTTP 通信とかできるのかな?
- Gemini マクロの移植とか考えたときにどうなるか
- プロパティ名が大文字小文字を区別する仕様
AddPosは OK、addPosはエラー。Alert()は OK、alert()はエラー。互換性を考えるとちょっと心配
>> enaka さん
> ボーランドを追放されたのち、カーンはカメラ付携帯電話を発明し、ヘルスバーグはMicrosoftでJ++とC# の開発をしたとか。
J++ は使ったことないのですが、C# は初めて触ったとき「え、Delphi にめっちゃ似てるやん!」って思いましたね (笑)
> 開発者5人以下&年間売り上げ千ドルまでは無料版の Community Editionが使えますから(笑)
そうなんですよね~。でも、ここ数年でライセンス規定がちょっと変わっちゃって…
昔は Professional 版を買えば、ライセンス認証の上限はあったものの、連絡すれば上限を増やしてもらえて、何度でも認証できたんですけど、それが廃止になっちゃって、上限超えたらアウトになっちゃったんですよね。
なので、OS のクリーンインストールや新しい PC にインストールすると、Delphi のライセンスを 1 つ消費しちゃうのが痛い…
Mery では Delphi XE2 (厳密に言うと、Delphi 10 Professional を買って、過去バージョンのライセンスが付属) を使っているのですが、もし PC が壊れたらライセンスが切れちゃって、新しく Delphi 12 Professional を買わないと XE2 のライセンスが手に入らなくなるので、実質 20 万円コースになっちゃいますね…
> 誤解を生む書き方ですいません。組み込んだJavascriptでは型推論が使えなくなるようです。
あ、なるほど!JavaScript 側の話でしたか。
JavaScript ってそもそも型がないイメージでしたが、型推論とかもあるんですね。勉強になります!
| Kuro | 返信 - スクリプトのエラーメッセージが英語のみ
-
> JavaScript ってそもそも型がないイメージでしたが、型推論とかもあるんですね。勉強になります!
そもそもJavaScriptは動的型付け言語なので型推論は必要なかったのですが、MicosoftがTypeScriptで(大規模開発用に)静的型付け言語として拡張した際、なるべく記述量を増やさないよう型推論を導入しました。
しかし、CとDelphiでは変数の保持や引数の渡し方が異なるため、JavaScriptからCとDelphiに返す変数の推論されるべき型がそれぞれ異なり、期待する動作にならない可能性があるからだとか。
Lazarusは、Delphi 8のdotNET対応により旧来のDelphiが死んだ、と判断した人たちが立ち上げたプロジェクトだそうです。
だからキリストが生き返らせた友人のラザロに由来した名称なんですね。ラザロ徴候のラザロだったのか。| enaka | 返信 -
> そもそもJavaScriptは動的型付け言語なので型推論は必要なかったのですが、MicosoftがTypeScriptで(大規模開発用に)静的型付け言語として拡張した際、なるべく記述量を増やさないよう型推論を導入しました。
なるほど、確かに TypeScript には型がありますね。
でも、TypeScript って JavaScript を作るためのツールですよね?
そう考えると、Delphi と JavaScript のやりとりには直接関係なさそうな気もしますが…
ただ、TypeScript → JavaScript の変換時に、型推論を使って JavaScript 側の型をある程度固定するような書き方にしてくれたりするのかも?
> しかし、CとDelphiでは変数の保持や引数の渡し方が異なるため、JavaScriptからCとDelphiに返す変数の推論されるべき型がそれぞれ異なり、期待する動作にならない可能性があるからだとか。
確かに、Delphi で JavaScript から変数を受け取ると、なんかよく分からない型の変数が飛んできて、Delphi 側でうまく処理しないといけないですね。
今までそれが普通のことだと思っていたので、特に気にしてませんでした (笑)
C だと JavaScript 側の型を自動で判別して受け取れたりするんですかね?もしそうなら、Delphi にはちょっと厳しい話ですね…
> Lazarusは、Delphi 8のdotNET対応により旧来のDelphiが死んだ、と判断した人たちが立ち上げたプロジェクトだそうです。
うはぁ、それは私も同意です。Delphi 5 から入ったので、Delphi 8 の .NET 対応にはかなりテンション下がりました (;^ω^)
Delphi 2009 でようやく昔の Delphi に戻りつつあったので、Delphi XE を買ったのですが、XE2 からまた変な方向に行き始めちゃって… (当時の FMX はバグだらけで使い物になりませんでした)
…と、語り出すと長くなっちゃいますね。(次回へ続く…のか!?)
| Kuro | 返信 -
> C++ 用のヘッダーファイル (plugin.h) もあるので、Delphi の書き方で迷ったときはそっちと見比べてみると、ヒントになるかもしれません。
ありがとうございます。ゆっくり試してみます😊 Delphiにも歴史あり、って感じでお二人の話も楽しく読ませてもらっています。
> 任天堂スイッチの自作アプリのフレームワークでも使われているとか、テンション上がりますね。
おお、本当だ。埋め込みエンジン、こうやって色々な展開があるのですね。
> quickjs.h は 1000 行ぐらいあるので、ここからは気合いと根性でコツコツ Delphi に翻訳するしかなさそうですね。
もし単純だけど量が多い系の作業であれば、生成AIに食わせてやってみるのも1つの手かも…?
> - HTTP 通信とかできるのかな?
> - Gemini マクロの移植とか考えたときにどうなるかたしかに…どうなんでしょう🤔
軽く調べた感じ、通信系は無いかもな感触でした。これは、呼び出し側の別言語で実装してそれを呼び出すみたいなカスタムが必要になるかもしれませんね。とはいえ、ほとんどのケースで通信するようなマクロって無いでしょうし、あったとしても「通信が発生する系=多少の遅延もやむなし」ですから、V8でも気にならないかもしれませんね。
そういう意味では、便利な通信系部品が揃ったV8と軽量エンジン (今はこれがJScript) という分担は、選択肢としていいのかもしれませんね。
| yuko | 返信 -
>でも、TypeScript って JavaScript を作るためのツールですよね?
斬新な表現(笑)
自分はTypeScript 上で型チェックをして問題ないことを確認し、JavaScriptにコンパイルするとソースから型が取り除かれるというイメージです。>そう考えると、Delphi と JavaScript のやりとりには直接関係なさそうな気もしますが…
>ただ、TypeScript → JavaScript の変換時に、型推論を使って JavaScript 側の型をある程度固定するような書き方にしてくれたりするのかも?JavaScript上の型の扱いは特有の型を除いてCと互換性があるが、Delphiとは互換性がないのでTypeScriptで型推論に頼った記述の型チェックが間違っているか無意味になる、ということだと思います。
>確かに、Delphi で JavaScript から変数を受け取ると、なんかよく分からない型の変数が飛んできて、Delphi 側でうまく処理しないといけないですね。
>今までそれが普通のことだと思っていたので、特に気にしてませんでした (笑)他者から受け取った値は信頼せずサニタイズし、他社に渡す値はきちんとサニタイズするのは、予期せぬバグを防ぐために重要ですよね。
グローバル変数で値をやり取りしている空中戦のようなコードとか、スタックに積んだ値の中間に飛び込んで書き替えるコードとか、メンテナンスが悪夢以外の何物でもない。| enaka | 返信 -
>> yuko さん
その後、QuickJS をいろいろ試していて、少しずつ使い方がわかってきた感じです。
> もし単純だけど量が多い系の作業であれば、生成AIに食わせてやってみるのも1つの手かも…?
試しに生成 AI に投げてみたのですが、結果はちょっと微妙でした。ポインタのポインタとか、Delphi で表現するにはちょっとコツがいるので、そこまでは難しいみたいです。
手作業だと、Delphi への翻訳自体はそんなに難しくないのですが、関数をひとつひとつ Delphi で書き直して動作チェックを繰り返すので、意外と時間がかかっちゃいますね。
> 軽く調べた感じ、通信系は無いかもな感触でした。これは、呼び出し側の別言語で実装してそれを呼び出すみたいなカスタムが必要になるかもしれませんね。
私も調べてみましたが、やっぱりそんな感じですね。
それか、QuickJS は外部モジュールを読み込めるみたいなので、通信系のモジュールがあれば import できるかも?🤔
> そういう意味では、便利な通信系部品が揃ったV8と軽量エンジン (今はこれがJScript) という分担は、選択肢としていいのかもしれませんね。
そうなると、現状のマクロの仕組みと QuickJS を使ったマクロの仕組み、どちらも共存させるかたちになりそうですね。
でも、ActiveScript が廃止されるとV8マクロはどうなっちゃうんでしょうかね…
ちょっと用語が難しいなと思ったので、整理してみました。
- COM (Component Object Model)
- Windows 上で異なるアプリや言語の間でやり取りするための技術。
- Windows の多くの部分で使われているので、廃止の可能性は低い?
- ActiveX
- COM 技術を利用する、クライアント側のコンポーネント。(主に ActiveX コントロールを指す)
- 廃止予定。特に Office 製品ではすでに無効化されている。
- ActiveScript
- Windows 上でスクリプトを実行する技術。
- COM 技術を利用する、ホスト側のスクリプトエンジン。
- 廃止の可能性あり。
- WSH
- Windows 上でスクリプトを実行するためのホストアプリケーション。
- ActiveScript エンジンを使ってスクリプトを動かす。
- 廃止の可能性あり。(PowerShell への移行が推奨されている)
- VBScript
- ActiveScript 上で動作するスクリプト言語。
- 廃止予定。
- JScript
- ActiveScript 上で動作するスクリプト言語。
- 廃止の可能性あり。
- V8 (WevView2)
- JavaScript エンジンであり、ActiveScript とは異なる技術。
- ただし、COM 技術を利用でき、外部アプリケーションを操作することも可能。
- QuickJS
- JavaScript エンジンであり、ActiveScript とは異なる技術。
- COM 技術を利用できない。
- Mery
- JScript は ActiveScript エンジンを利用。
- V8 は WebView2 の JavaScript エンジンを利用。
- どちらも COM 技術を使っているので、実装はほぼ共通。
という感じで、ポイントは ActiveScript と WSH の違いですね。
WSH は ActiveScript を利用するアプリケーションなので、たとえるなら Mery のような位置付けです。
今後、廃止される可能性が高いのは WSH ですが、WSH がなくなっても ActiveScript 自体が同時に無くなるわけではないようです。
…が、ActiveScript はすでに非推奨になっているので、VBScript の廃止 → JScript の廃止 → ActiveScript の廃止、って流れは十分ありそうですね。
とはいえ、ActiveScript が廃止されても COM 技術が廃止されるわけではないので、WebView2 の V8 を使ったマクロは引き続き利用できるのではないかと推測しています。
でも、JScript 廃止の可能性は高いので、QuickJS みたいな組み込みマクロの実装は必要になりそうですね。
>> enaka さん
> JavaScript上の型の扱いは特有の型を除いてCと互換性があるが、Delphiとは互換性がないのでTypeScriptで型推論に頼った記述の型チェックが間違っているか無意味になる、ということだと思います。
なるほど、そういうことだったんですね。JavaScript の変数の型をうまく受け取れないのは、まさか Delphi の仕様が原因だったとは…
> グローバル変数で値をやり取りしている空中戦のようなコードとか、スタックに積んだ値の中間に飛び込んで書き替えるコードとか、メンテナンスが悪夢以外の何物でもない。
ドキッ。確かに、グローバル変数で空中戦、やっちゃってますね。
オブジェクト指向は便利ですが、Mery では動作速度を優先する場合、どうしても手続き型が有利で、グローバル変数の使いどころとしてはそんな感じで使ってます。
開発チームが私ひとりだからできることかも (笑)
| Kuro | 返信 - COM (Component Object Model)
-
> それか、QuickJS は外部モジュールを読み込めるみたいなので、通信系のモジュールがあれば import できるかも?🤔
おおー、組み込み用途の軽量エンジンを謳うくらいですから、IoT機器に組み込まれることも多そうですし、となると機器からHTTP通信を実現したくなるのが人の性…どこかでそんな素敵部品を公開してくださっている方が居ても不思議ではないですね。
> ちょっと用語が難しいなと思ったので、整理してみました。
ありがとうございます。色々と関係が分からなくなってきていたので、助かりますw
こうやって並べて見てみると、やっぱりJScriptの行く末はやっぱり心配ですね…。たしかに、JScriptが塞がれれば自然とWSHも使い道がほとんど無くなるということで、合わせて廃止になりそうです。
ActiveScriptよりもJScriptの廃止の方が可能性が高そうと感じてしまいますね。メンテコストとセキュリティリスクからVBScriptは切り捨てられたのでしょうが、その理由で言えばJScriptだって同じ穴のムジナなような…🤔
QuickJSのような組み込みエンジンがあれば、新機能という楽しみもありますが、Meryが永く使い続けられるという安心材料としても嬉しい感じです。
| yuko | 返信 -
>それか、QuickJS は外部モジュールを読み込めるみたいなので、通信系のモジュールがあれば import できるかも?🤔
QuickJS自体は手段として用意しておくのはありだとは思いますが、足りないランタイムAPIを外部モジュールで補うのはモジュール自体の妥当性・安全性・継続性やAPIの普遍性などが気になりますね。ランタイムAPIについては…
参考:https://qiita.com/access3151fq/items/829f681d530ef6129c8d
参考:https://zenn.dev/itte/articles/5c8e5c191e386b (記事先頭から「JavaScriptエンジンとJavaScriptランタイム」の最後まで)個人的にはどうにかNode.jsかDenoを介せるようになった方がいいですね。(どちらかといえばDeno推し)
WinterTCがWeb標準に影響をもたらすようになると考えられ、そのメンバーである両者はそれに従う可能性が高いので。
※WinterTCはWinterCGという非Webブラウザ環境(主にサーバサイド)におけるJavaScriptの互換性を目指していたコミュニティが先月(2025年01月)にEcma International傘下(TC55)に移行したもの。
※TC39がECMAScript(=JavaScript)を標準化していて、メンバーの多くがそちらなどにも既に参加していたためEcmaに移ることになったらしい。参考にはならないかも知れないけれど、一応前例としてはDenoでVim/Neovim用プラグインを作れるdenops.vimがあるようです。(Vimmerじゃないから詳しくは知らない)
| barrackdo | 返信 -
>オブジェクト指向は便利ですが、Mery では動作速度を優先する場合、どうしても手続き型が有利で、グローバル変数の使いどころとしてはそんな感じで使ってます。
サンダーバードのオープニングを歌いながら、グローバル変数を駆使したコーディングをしていた同僚を思い出します。
「原子力機ファイアーフラッシュ号の危機」という、24時間ごとに放射能防御隔壁を交換する必要がある原子力飛行機が飛行中に行方不明になり、捜索・発見したサンダーバードチームが飛行中に放射能防御隔壁を交換するというエピソードがあるんです。>今後、廃止される可能性が高いのは WSH ですが、WSH がなくなっても ActiveScript 自体が同時に無くなるわけではないようです。
多分、かつてのshell32.dll内のアニメーションのAPIのように、Microsoft製品以外からは呼び出すことができないようになるんだと予想しています。
| enaka | 返信 -
>> barrackdo さん
> QuickJS自体は手段として用意しておくのはありだとは思いますが、足りないランタイムAPIを外部モジュールで補うのはモジュール自体の妥当性・安全性・継続性やAPIの普遍性などが気になりますね。
確かに、外部モジュールに依存すると、妥当性や継続性のリスクはありますね。
特に Mery のようなテキストエディターでは、長期間の安定動作が求められるので、慎重に考えるべきポイントだと思います。
> 個人的にはどうにかNode.jsかDenoを介せるようになった方がいいですね。(どちらかといえばDeno推し)
なるほど、詳細な情報をありがとうございます。
Deno は名前くらいしか知らなかったのですが、軽く調べてみた感じだと、Deno も C++ で書かれているようなので、DLL として使える可能性はありそうですね。
ただ、V8 エンジンを使っているので、ファイルサイズがかなり大きくなりそうな予感も…
そういえば、EmEditor さんが、恐らく LSP 対応のためだと思いますが、Node.js を同梱されていました。
同梱されているファイルサイズは 80MB ほどあるので、Mery のようなフリーソフトの方向性としてはちょっと重いかなといった印象です。
その点、QuickJS は 700KB くらいで、すごく軽いんですよね。
> 参考にはならないかも知れないけれど、一応前例としてはDenoでVim/Neovim用プラグインを作れるdenops.vimがあるようです。(Vimmerじゃないから詳しくは知らない)
面白そうですね!
ローカルに Deno をインストールして、Vim のプラグインと Deno がコマンドライン経由でやり取りしている感じなんですかね?もしそうだとしたら、かなり興味深い仕組みですね。
>> enaka さん
> サンダーバードのオープニングを歌いながら、グローバル変数を駆使したコーディングをしていた同僚を思い出します。
それ、かなりロックな魂を感じますね (笑)
> 「原子力機ファイアーフラッシュ号の危機」という、24時間ごとに放射能防御隔壁を交換する必要がある原子力飛行機が飛行中に行方不明になり、捜索・発見したサンダーバードチームが飛行中に放射能防御隔壁を交換するというエピソードがあるんです。
今のご時世だとちょっと怒られそうなエピソード (笑) でも、グローバル変数は「飛び交う放射性物質」って言われれば、確かにそんな感じかもしれませんね。
隔壁をなくして機体 (プログラム) を軽くすると、代わりに開発者の命が削られる、まさにサンダーバード的開発方式ですね。
> 多分、かつてのshell32.dll内のアニメーションのAPIのように、Microsoft製品以外からは呼び出すことができないようになるんだと予想しています。
Microsoft さん、よくやりますよね。Mery でもダークモードを実装するために、非公開の API を叩いてます。
でもほんと、Microsoft 製品だけ VBScript が使えるとか、そんな感じはありそうですね。
| Kuro | 返信 -
quickjs-ng ですが、
quickjs.hの Delphi 書き換えがほぼ完了し、Mery に組み込めるところまで進んだので、ご報告です😉とりあえず、
document.selection.Text = "mery"が動くようになりました。できたこと
- 標準モジュール (
qjs:std、qjs:os、qjs:bjson) の組み込み- ローカルファイルへのアクセスやコマンドライン操作など、ActiveX でやっていたようなことができそう。
- ただし、Windows では動作しない機能もあり、組み込みの必要性は要検討。
- サンプル:
import * as os from "qjs:os";
- 外部モジュールの読み込み
.jsファイルを外部モジュールとして読み込む機能の実装。#includeに似たようなものなので、必要性は要検討。- サンプル:
import { fib } from "./fib_module.js";
- 正規表現の使用
new RegExpが使え、Mery に同梱のFilter.jsも動作。- これが動かないとキツイと思っていたので一安心。
- 非同期処理
- 新しく実装した
#async = trueを指定することで、非同期マクロの実行に対応できそう。
- 新しく実装した
window > document > selectionの階層構造の実現- 情報が少なすぎて手探りでしたが、できたときは飛んで喜びました😫
window === globalThisの実現- JScript や V8 と同様、
windowがglobalThisを指すような仕様を実装。 - これにより、
windowの省略記述が可能になり、従来のマクロとの、ある程度の互換性を確保。
- JScript や V8 と同様、
できなかったこと・微妙なこと
- Windows 7 以降が必須
- quickjs は Windows XP でも動いたけど、quickjs-ng は Windows 7 以降が必須。(VS >= 2022 and Clang are supported)
- まぁ、V8 なんて Windows 10 以降が必要だし、いいかしら。
std.urlGetが動作しない- 「HTTP アクセスできるじゃん!」と思ったけど、なぜか動かず。
binaryオプションがあってストリーミング受信できそうなのに…
- エラーのスタックトレースが雑
- スクリプトエラーの位置は拾えるけど、かなり大雑把。
- すぐに「1:1」とか言い出す。
今後の作業
あとは一心不乱に Mery のマクロのプロパティやメソッドを quickjs 方式に書き直していくのみ。
とりあえず、呼び出し方は
#language = "quickjs"でいこうかなと。…と、すでに後には引けない状態になっています😂
個人的には quickjs-ng は「アリ」かなと思っていますが、情報が少なすぎるのが難点ですね。
ご興味のある方は、quickjs-ng をビルドすると qjs.exe というローカルで動作するシンプルなアプリ (いわゆる WSH みたいなやつ) が生成されます。
qjs.exe C:\Temp\a.jsのように実行すればスクリプトを動かせるので、試してみて情報共有していただけると嬉しいです。また、Mery のマクロ機能の互換性について、気になる点や制限事項になりそうな点があれば、ぜひ教えてください!
| Kuro | 返信 - 標準モジュール (
-
おおっ、QuickJS組み込み、日の目を見る日も近い…!?
exe もビルドが簡単、ということはリリースページにビルド済み実行ファイルもあるかな…?と思ってみたら、やっぱりありました。
https://github.com/quickjs-ng/quickjs/releases
→ qjs-windows-x86.exe / qjs-windows-x86_64.exeこれでできることが、Meryでも搭載したら使えるようになるってことですよね。面白そう。ちょっと動かして遊んでみます。
取り急ぎ、1つのフォルダーに実行ファイルと生jsを突っ込んで以下の通り実行。サクッと動きました。
❯ .\qjs-windows-x86_64.exe .\hello-world.js Hello, World!雑談スレなので横道に逸れますが、思い立って最近
<textarea>をMarkdownエディター風味にするコードを書いていまして、だいぶ安定してきたのでひっそり公開してみました。パブリックドメインとしているので、面白そうならフォーラムのテキストエリアで使ってみたり、改造したり、著作権表示無しでご自由に使っていただいて構いません。
https://gist.github.com/yuru7/1c72d92ade8a83bad5a3eea32f8f51e9末尾あたりにあるような感じで、「インスタンス化 → enable()」とすると動くはずです。
const target = document.querySelector('textarea'); const mdTextarea = new MDTextarea(target); mdTextarea.enable();主な機能:
- 改行時にMarkdownの番号付き/番号なしリスト記号の付与
- 改行時にインデント引き継ぎ
- Tab/Shift+Tab でインデント/アウトデント
- 改行、インデント、アウトデント時には番号付きリスト再採番 (下方向にのみ)
ちなみに、ブラウザのundoスタックに編集を格納したいがために、
textarea.value = "VALUE"を使わずに、ひたすらdocument.execCommand('insertText')で頑張っています…w| yuko | 返信 -
console.log(Object.keys(globalThis))で、グローバルオブジェクトがどれほどあるのかをQuickJS-NGで見てみると、7個ほどしか無く、本当にすっきりで驚きました。ブラウザで同じ出力を見ると、200個を超える項目が…そう考えるとQuickJS-NGは本当にコアエンジンって感じですね。やっぱり、fetchのような外部通信は別途実装よろしくな感じなんですね。
あと先ほど、QuickJS-NGのメインメンテナーの方がQuickJS-NGを基礎にして構築した実行環境も見つけました。QuickJS-NGを組み込んで使っているという意味では今回のMeryのような立ち位置に近いのかな、なんて思いました。
https://github.com/saghul/txiki.jstxiki.js ではfetchも追加実装されているようですね。以下のような処理が動かせました。
.\txiki-windows-x86_64\tjs.exe run .\fetch-demo.js ※fetch-demo.js の中身は後述// Open-Meteo APIを使用して天気情報を取得 const apiUrl = 'http://api.open-meteo.com/v1/forecast?latitude=35.5&longitude=138.4&hourly=temperature_2m&timezone=Asia%2FTokyo&forecast_days=1'; fetch(apiUrl) .then(response => { // レスポンスが正常か確認 if (!response.ok) { throw new Error(`HTTPエラー! ステータス: ${response.status}`); } return response.json(); // JSON形式に変換 }) .then(data => { console.log('取得したデータ:', data); // データ全体を表示 // 時間ごとの気温を表示 data.hourly.temperature_2m.forEach((temperature, index) => { console.log(`時間: ${data.hourly.time[index]} - 気温: ${temperature}°C`); }); }) .catch(error => { console.error('エラーが発生しました:', error); // エラーハンドリング });上記で叩いているページはhttpsでも扱えるのですが、httpsにするとエラーになってしまうので、SSL処理周りで何かがうまくいかないのでしょう…
| yuko | 返信 -
WSH (cscript.exe) とQuickJS-NG (qjs-windows-x86_64.exe) で簡易的なベンチマークをしてみました (オマケでV8も)。V8はさすがに速いですが、QuickJS-NGもWSH比で倍以上の速度。これでリードタイムがほぼ皆無ということであれば、やっぱり良いですね。
# QuickJS-NG 2288.00ms 2290.00ms 2286.00ms # WSH 5953.00ms 5979.00ms 6056.00ms # V8 (Chrome v133) 563.00ms 599.00ms 605.00msテストコード:
function benchmark() { // var start = performance.now(); var start = new Date().getTime(); // 算術演算テスト var mathResult = 0; for (var i = 0; i < 1e7; i++) { mathResult += Math.sqrt(i) * Math.pow(i, 0.5); } // オブジェクト操作テスト var objTest = {}; for (var j = 0; j < 1e6; j++) { objTest['key' + j] = j * 2; delete objTest['key' + (j - 100)]; } // 関数呼び出しテスト function recursive(n) { if (n <= 1) { return 1; } return n * recursive(n - 1); } var factorial = recursive(50); // var end = performance.now(); var end = new Date().getTime(); return (end - start).toFixed(2) + 'ms'; } for (var i = 0; i < 3; i++) { // QuickJSの場合 console.log(benchmark()); // WSHの場合 // WScript.Echo(benchmark()); }| yuko | 返信 -
> おおっ、QuickJS組み込み、日の目を見る日も近い…!?
3 連休、精神と時の部屋で過ごしましたが、まだまだ…。でも、「1 年ぐらいかけての計画」と言いましたが、そこまではかからないかも?😉
> 雑談スレなので横道に逸れますが、思い立って最近 <textarea> をMarkdownエディター風味にするコードを書いていまして、だいぶ安定してきたのでひっそり公開してみました。
おおっ!試しにローカルサーバーに導入してみましたが、いい感じですね!
シンプルだけど、バックスペースなどの細かい操作に気が利いているし、Undo が効く謎の技術w こういうセンス、最高です。
このフォーラムでも使わせていただきたいです。
> console.log(Object.keys(globalThis)) で、グローバルオブジェクトがどれほどあるのかをQuickJS-NGで見てみると、7個ほどしか無く、本当にすっきりで驚きました。
Mery で素の QuickJS の DLL を実行すると、performance と console のみなので、それ以外は qjs.exe (ランタイム側) で実装されているみたいですね。
そこに Mery の機能の、alert とか document とか outputBar とかのプロパティを実装してく感じです。
> txiki.js ではfetchも追加実装されているようですね。以下のような処理が動かせました。
情報ありがとうございます。
txiki.js のソースをチラッと拝見したところ、curl-websocket.c などが見えたので、C のモジュールを組み込んでいるっぽいですね。
そう考えると、Edge なんかも fetch の機能って V8 エンジン側じゃなくて、ランタイム側にあるのかも?
> WSH (cscript.exe) とQuickJS-NG (qjs-windows-x86_64.exe) で簡易的なベンチマークをしてみました (オマケでV8も)。V8はさすがに速いですが、QuickJS-NGもWSH比で倍以上の速度。これでリードタイムがほぼ皆無ということであれば、やっぱり良いですね。
ベンチマークのスクリプト、ありがたいです!
私の環境でも試してみたところ、なかなか興味深い結果が…
# QuickJS-NG (qjs-windows-x86_64.exe) 2547.00ms 3183.00ms 3171.00ms # WSH (JScript Version: 11.0.16384) 6907.00ms 6931.00ms 7012.00ms # V8 (Chrome v133) 460.00ms 452.00ms 441.00ms私の PC はポンコツなので yuko さんの環境より遅いはず…と思いきや、なぜか Chrome だけは速いという謎w
で、次に、自分でビルドした QuickJS-NG のテストです。
Visual Studio 2022 でビルド
# QuickJS-NG (qjs.exe 32 ビット版) 3285.00ms 3281.00ms 3285.00ms # QuickJS-NG (qjs.exe 64 ビット版) 2767.00ms 2762.00ms 2757.00ms次に、Mery から DLL 経由での呼び出しです。
#language = "quickjs" // qjs.dll 32 ビット 3406.00ms 3395.00ms 3403.00ms #language = "quickjs" // qjs.dll 64 ビット クラッシュ😱 #language 指定なし (JScript Version: 11.0.16384) // JSCRIPT9.dll 1339.00ms 1255.00ms 1288.00ms #language = "javascript" (JScript Version: 11.0.16384) // JSCRIPT9LEGACY.dll 5666.00ms 5757.00ms 5709.00ms #language = "v8" // WebView2 931.00ms 1010.00ms 1116.00msMery では、
#languageを指定しない場合は JSCRIPT9.dll (Chakra) を使います。明示的に
#language = "javascript"を指定した場合は WSH と同様、OS 依存の JScript を使いますが、Windows 10 までは JScript 5 とかだった気がするんですよね。でも、Windows 11 では JSCRIPT9LEGACY.dll というものが呼ばれるようになってるみたいです。
JSCRIPT9LEGACY.dll の JScript もバージョン 11.0.16384 ということで Chakra と同じなのですが、なぜか JSCRIPT9.dll より圧倒的に遅いという謎…
さらに、QuickJS-NG より JSCRIPT9.dll (現在の Mery のデフォルト) のほうが速いという悲しみ…
そしてトドメに、QuickJS-NG の 64ビット版の DLL が動かないことが判明し、意気消沈。道のりは、まだ長そうです…🫠
| Kuro | 返信 -
> このフォーラムでも使わせていただきたいです。
どうぞどうぞ。どこかで役立ててもらえたら、作った甲斐もあります😁
ちなみにMarkdownエディター"風"ということで、リスト記号として「・」も判定されるようになっていたり、インデント判定に全角スペースも入っていたりと、ラフに使いやすい仕様にしておきました。
> txiki.js のソースをチラッと拝見したところ、curl-websocket.c などが見えたので、C のモジュールを組み込んでいるっぽいですね。
やっぱり追加実装な感じですよね。
setTimeout, setIntervalなんかもtxiki.jsで追加されているような説明がREADMEに書かれているので、何かとかゆいところに手が届く的な機能追加がされている印象。もしいつか、Meryで実装するQuickJSで、V8との機能差分で不便になりそうなところを埋めようと思ったらtxiki.jsの追加項目は参考になるかもしれませんね。個人的には、
fetch, setTimeout, setIntervalあたりがあると、Web通信と動作タイミングの調整が自由にできるので嬉しいですね。そうは言ってもGeminiさんマクロくらいでしか私もfetchを使っていないですし、活用場面は多くないんでしょうけれど…😅 setTimeoutに関しては、MeryのSleep関数がそのまま代替になってくれると良いですが、思えば非同期処理中のSleep関数の動きって見たことなかった気がします。> でも、Windows 11 では JSCRIPT9LEGACY.dll というものが呼ばれるようになってるみたいです。
>
> JSCRIPT9LEGACY.dll の JScript もバージョン 11.0.16384 ということで Chakra と同じなのですが、なぜか JSCRIPT9.dll より圧倒的に遅いという謎…https://learn.microsoft.com/en-us/answers/questions/2130135/jscript-runtime-error-in-windows-11-24h2 の内容を見る限り、脆弱性対応済みのものが「JSCRIPT9LEGACY.dll 」ということなんでしょうかね🤔
C:\Windows\SysWOW64\内にあるjscript9.dll, jscript9Legacy.dllのファイルサイズをそれぞれ見ると、確かに差分があるように見えます。
脆弱性対応っていうと、パフォーマンスとのトレードオフ的な対応がされることも少なくありませんから、そういうことなのかもしれませんね…。というか、上記スレッドの報告を見る限り、パフォーマンスだけじゃなくって機能的にも差分があるのかもしれませんが…。
> さらに、QuickJS-NG より JSCRIPT9.dll (現在の Mery のデフォルト) のほうが速いという悲しみ…
脆弱性対応が契機で入った、ということであれば、Legacy版だけ残してJSCRIPT9.dll が消える未来すらあり得るわけですよね…。そうなればQuickJS-NGの方がJScript (Legacy) よりも速い & 組み込みなのでJScriptの生存に左右されない安心感、というのはやっぱりありそうです。
> そしてトドメに、QuickJS-NG の 64ビット版の DLL が動かないことが判明し、意気消沈。道のりは、まだ長そうです…🫠
あらら…健闘を全力で祈ります!
| yuko | 返信 -
> どうぞどうぞ。どこかで役立ててもらえたら、作った甲斐もあります😁
ありがとうございます!週末あたりに時間が取れたら、フォーラムへの組み込みを試してみます😊
> リスト記号として「・」も判定されるようになっていたり、インデント判定に全角スペースも入っていたり
なるほどー。[マークダウンを有効にする] のときだけ適用する想定でしたが、プレーンテキストでも使えたほうが便利かもしれませんね。
> 個人的には、 fetch, setTimeout, setInterval あたりがあると、Web通信と動作タイミングの調整が自由にできるので嬉しいですね。
QuickJS にオマケでついてる標準モジュール (qjs:os) には
setTimeout、setIntervalが実装されてますね。qjs-windows-x86_64.exe test.jsimport * as os from "qjs:os"; var i = 0; function task() { console.log(i); i++; os.setTimeout(task, 1000); } task();ただ、txiki.js では標準モジュールを使わず、自前で実装しているようです。
QuickJS の標準モジュールは
os、std、bjsonの 3 つがありますが、osとstdは OS 依存の部分が多く、うまく動かない機能もあるので、使わないほうがいいのかなーとも思い始めました。> もしいつか、Meryで実装するQuickJSで、V8との機能差分で不便になりそうなところを埋めようと思ったらtxiki.jsの追加項目は参考になるかもしれませんね。
txiki.js のソースを読んでみたところ、
fetchメソッドはlibcurl.dllを使っているようですね。DLL なら Mery に組み込める可能性はありますが、なかなか大変なことになりそうです。
どうせ curl を組み込むなら、標準機能で AI サポート的なものを入れるのもアリかも…
そういえば、Gemini Code Assist が個人向けに無料版として提供されると発表されましたね。これかー🫠
> あらら…健闘を全力で祈ります!
ありがとうございます!なんとか 64 ビット版も動作するようになりました。
どうやら QuickJS は 32 ビットと 64 ビットで処理を分岐してる部分があるみたいで、こりゃ大変だぞー…という感じです😩
ということで、ベンチマーク…
#language = "quickjs" // qjs.dll 64 ビット 2998.00ms 2973.00ms 2960.00ms32 ビット版より少し速いですね。あと、DLL (動的リンク) だと、LIB (静的リンク) より若干遅くなるのはあるかもです。
> 脆弱性対応が契機で入った、ということであれば、Legacy版だけ残してJSCRIPT9.dll が消える未来すらあり得るわけですよね…。そうなればQuickJS-NGの方がJScript (Legacy) よりも速い & 組み込みなのでJScriptの生存に左右されない安心感、というのはやっぱりありそうです。
それはありそうですね。
QuickJS-NG も将来性という点では不安が残りますが、しがらみのない個人開発の野良アプリには向いてる気がしますね。
遊び道具としては「コレコレ!」って感じw でも、有料化計画とは真逆の方向に…
まぁ、このご時世、テキストエディターにお金払う人もいませんよね、とほほ😂
| Kuro | 返信 -
> まぁ、このご時世、テキストエディターにお金払う人もいませんよね、とほほ😂
何年か前のviviの開発再開クラウドファンディングで何十万円というレベルですしね。続報ないですし。
年一回、Delphi更新とリリースのための署名の資金をクラウドファンディングするぐらいが現実的でしょうか?以下雑談ネタ投下。
Cのソースで28行しかないviライクなフルスクリーンテキストエディタを見つけました。IOCCC91でのBest Utility作品だそうです。
https://github.com/SirWumpus/ioccc-ae/blob/master/91/ant.c
何をしているのかさっぱり理解できなかったのですが、120行に読みやすく書き直して解説している方がおられました。
http://gurakura.sakura.ne.jp/culture/vi-like_text_editor_by_120_lines/
まるで魔法のようです。| enaka | 返信 -
>> enaka さん
情報ありがとうございます!
> 何年か前のviviの開発再開クラウドファンディングで何十万円というレベルですしね。続報ないですし。
うはぁ、vivi 懐かしいですね。会社の先輩が当時課金してたのを思い出しました。
ちょっと触らせてもらったら、操作がめちゃくちゃ難しそうで「これは無理!」ってなったのですが、今となっては
viなら普通に使ってるし、すごく貴重なエディターだったんだなぁとしみじみ思います。その頃にはすでに Mery を作ってはいたのですが、
viのことなんてまったく知らなかったので、今考えるとちょっと恥ずかしいですね。しかし、vivi さんですら数十万円とは…。秀丸エディタさんが数億円稼いでたって話には夢がありましたが、現実はなかなか厳しいですねぇ。
> 年一回、Delphi更新とリリースのための署名の資金をクラウドファンディングするぐらいが現実的でしょうか?
それやっちゃいます?持ち逃げしちゃうかも!てへぺろ (嘘です)
> Cのソースで28行しかないviライクなフルスクリーンテキストエディタを見つけました。IOCCC91でのBest Utility作品だそうです。
拝見…。絶対無理なやつや!(笑)
ビルドしてみようかなと思ったのですが、README を読んだ感じだと Windows ではちょっと厳しそうですね…
> 何をしているのかさっぱり理解できなかったのですが、120行に読みやすく書き直して解説している方がおられました。
おお、興味深いですね!こうして「翻訳」されると、テキストエディター作ってる身としては何となく分かる気がします。
当時は GUI がないぶん、シンプルに実装できたのかもしれませんが、それでも 120 行はすごいですね。Mery のソースコードの行数、今度数えてみようかな… (怖くて見たくないけどw)
>> yuko さん
その後、
fetchをいろいろ研究していたのですが、ちょっと心が折れたので進捗報告です。> どうせ curl を組み込むなら、標準機能で AI サポート的なものを入れるのもアリかも…
こんなことを言っちゃったのは、Delphi で意外と簡単に libcurl.dll を実装できたので「これはイケるんじゃね?」と思ってしまったからなのですが…
その後、txiki.js のソースをガッツリ読んでいくと、fetch の実装には libcurl だけじゃなく、libuv も組み込まれてることが判明。
で、libuv って何かというと、Node.js でも使われてる非同期処理のライブラリなんですよね。
fetchを 3 回ぐらい呼んで、それぞれthenで結果を受け取れるのって、まさに非同期処理の恩恵。つまり、これを Mery に組み込もうとすると、ちっちゃい Node.js を作るようなもので、かなり厳しい状況です。まぁ、その「ちっちゃい Node.js」こそが txiki.js なんでしょうけど。
一応、見よう見まねで非同期じゃない「なんちゃって fetch」みたいなのは作れました。
ただ、日本語のエンコード処理までは curl がやってくれないみたいで、文字化けして使い物にならず。(txiki.js も日本語は文字化けするっぽいですね)
さらに、
setTimeoutやsetIntervalも同様に libuv の非同期処理に依存しているので、これらの機能を実装するのはホスト (ランタイム) 側のお仕事ではありますが、 Mery でやるには、若干、ヘビーすぎるかなといったところです。なので、Mery 的には、QuickJS はとりあえず ActiveScript マクロの引っ越し先くらいの立ち位置にして、
fetchみたいな非同期処理は V8 に丸投げしちゃうのが平和かな、というのが現時点での落としどころかなと。かなり苦労があったので、この結論は残念ですが…😩
| Kuro | 返信 -
> その後、fetchをいろいろ研究していたのですが、ちょっと心が折れたので進捗報告です。
> なので、Mery 的には、QuickJS はとりあえず ActiveScript マクロの引っ越し先くらいの立ち位置にして、`fetch`みたいな非同期処理は V8 に丸投げしちゃうのが平和かな、というのが現時点での落としどころかなと。oh…お疲れさまでした…😭
良い感じのfetch搭載、やろうとしたらそれこそ一大プロジェクトになっちゃいますね。まずはQuickJSが動くところまでを1つの区切りとしてしまったほうが良さそうです。でも今後、Mery自前で拡張できる可能性があるという点では、(拡張もまた大変なのはさておき) なかなか夢の広がる機能追加になりそうですね😊
思いつきですが、JScriptやQuickJSのような軽量起動なやつから、V8で動くマクロを途中で呼び出せる機構があれば、あのV8起動時のリードタイムも多少は目をつむれそうな気はしますが、そういうのも難しいでしょうかね?
例えば、右クリックメニューはJScriptかQuickJSでサッと表示してしまって、メニュー項目選択後の処理部分でV8マクロを呼び出すみたいな…| yuko | 返信 -
> 良い感じのfetch搭載、やろうとしたらそれこそ一大プロジェクトになっちゃいますね。
txiki.js の場合、低いレイヤーから順に
libuv → libcurl → XMLHttpRequest → fetchって感じで実装されてるみたいですが、libuvはお手軽に使える感じじゃないですし、fetchもresponse.body.getReader()が未実装なので、Gemini マクロのストリーミングもできなさそうで、ちょっと物足りないですね。> でも今後、Mery自前で拡張できる可能性があるという点では、(拡張もまた大変なのはさておき) なかなか夢の広がる機能追加になりそうですね😊
そうですね。可能性としては面白いのですが、いざやろうとすると低レイヤーの知識が必要になってくるので、なかなか骨が折れそうです🤷♂️
> 思いつきですが、JScriptやQuickJSのような軽量起動なやつから、V8で動くマクロを途中で呼び出せる機構があれば、あのV8起動時のリードタイムも多少は目をつむれそうな気はしますが、そういうのも難しいでしょうかね?
一応、プラグインならマクロを呼び出せる機能があるので、それっぽいことはできますね。
ただ、マクロからさらにマクロを呼び出すとなると、再帰的な処理になりそうで、実装がけっこう大変そうです。
> 例えば、右クリックメニューはJScriptかQuickJSでサッと表示してしまって、メニュー項目選択後の処理部分でV8マクロを呼び出すみたいな…
なるほど。確かに、メニューの表示自体がもっさりするのは避けたいですよね。
QuickJS や fetch とは関係なく、そのあたりの仕組みがあると便利そうなので、技術的にいけそうかちょっと調べてみます。
| Kuro | 返信 -
> > 例えば、右クリックメニューはJScriptかQuickJSでサッと表示してしまって、メニュー項目選択後の処理部分でV8マクロを呼び出すみたいな…
意図するところは伝わったかもしれませんが、「右クリックメニュー」ではなく「ポップアップメニュー (MeryのPopupMenuオブジェクト)」の間違いでした…😅
Geminiさん相談マクロ、ショートカットキーに設定して便利に使っているものの、ポップアップメニュー表示を1秒くらい待つので、時々「あれ、今キー打ち損じたかな?」って一瞬勘違いしてしまうのが玉に瑕…V8初動部分を遅延起動みたいにできたら嬉しいですね。
| yuko | 返信 -
悲しいときー。
libcurlを学ぶXMLHttpRequestを Delphi で実装- 同期版
fetchを実装 - 文字化け対策で
TextDecoderを実装 libuvを学ぶ- 非同期版
fetchを実装 ← いまここ
からの…
quickjs+libuv+libcurlだと、どう頑張ってもuv_poll_startのコールバックが呼ばれない😱これさえ動けば
fetchの実装、いける気がしてたのに…ちなみに、
libuvのタイマーとかアイドルのコールバックは普通に呼ばれるんですよね。土日まるっと費やしたのに、成果ゼロ😭考えられる原因は…
libuvの使い方、間違ってる?libuv+libcurlのバージョン相性問題?libuvの Delphi への翻訳ミス?
あれこれ試したけど、もはやお手上げ🤷♂️ このチャレンジはいったん終了します!
>> yuko さん
> 意図するところは伝わったかもしれませんが、「右クリックメニュー」ではなく「ポップアップメニュー (MeryのPopupMenuオブジェクト)」の間違いでした…😅
最初は、右クリックメニューに登録してるマクロの名前の横に「昇順に並べ替え (JScript)」、「Gemini に相談 (V8)」とか表示して、このマクロは V8 だから起動が遅いけど覚悟しろよー、っていう機能なのかと思いました😅
> Geminiさん相談マクロ、ショートカットキーに設定して便利に使っているものの、ポップアップメニュー表示を1秒くらい待つので、時々「あれ、今キー打ち損じたかな?」って一瞬勘違いしてしまうのが玉に瑕…V8初動部分を遅延起動みたいにできたら嬉しいですね。
まだ検証中ですが、一応「マクロからマクロを呼び出す機能」、実装できるかも?ってとこまでは来ました。
ただ、「マクロ → マクロ → さらにマクロ」みたいに ネストしていった場合、ちゃんと動くのか?っていうのは、まだちょっと怪しいですが…
| Kuro | 返信 -
> ちなみに、`libuv`のタイマーとかアイドルのコールバックは普通に呼ばれるんですよね。土日まるっと費やしたのに、成果ゼロ😭
週末パワーでも太刀打ちならずでしたか…。コールバックが完全に効かないかと思うと別の関数では使えるということで微妙に希望を見せられたりして、悶々とする感じでムムムとなりますね…😫
> まだ検証中ですが、一応「マクロからマクロを呼び出す機能」、実装できるかも?ってとこまでは来ました。
> ただ、「マクロ → マクロ → さらにマクロ」みたいに ネストしていった場合、ちゃんと動くのか?っていうのは、まだちょっと怪しいですが…おおー、素晴らしい!
動作がちょっと心配なら、「マクロ → マクロ」はいいけど、「マクロ → マクロ → さらにマクロ」はできないように塞いでしまうのも一案かもしれませんね。今回は途中でのエンジン切り替えが主なところなので「マクロ → マクロ」ができれば十分ですし。
あまり用途は考えられないものの、もしも複数回のエンジン切り替えが必要な場面があったら多層呼び出しにならないように「メインロジック (JScript) -> サブロジック (V8) 呼び出し -> 処理が戻ってきたことを確認 -> サブロジック (QuckJS) 呼び出し」とかマクロの作りですればいい気がします。あ、でもそういうの考えるとサブロジックから戻り値を受け取りたくなったりするのかしら…🤔
| yuko | 返信 -
> ちなみに、`libuv`のタイマーとかアイドルのコールバックは普通に呼ばれるんですよね。土日まるっと費やしたのに、成果ゼロ😭
Oh
より簡単なTinyUVライブラリから調べるとよいかも。以下wikiがわかりやすい。
https://github.com/Samsung/libtuv個人的に、非同期通信ならMQTTプロトコルとか喋れると面白いことが出来るかな、と思っています。
以下雑談ネタ投下libtuvつながりでSamsungがTizenOSのために作ったJavascript Engine、JerryScriptがとても小さくていい感じ。
https://github.com/jerryscript-project/
https://jerryscript.netQuickJS以外にJavascript Engineを結構いろいろ見つけました。
https://bestofjs.org/projects?tags=runtime
https://docs.sheetjs.com/docs/demos/engines/
https://bellard.org/quickjs/bench.html| enaka | 返信 -
>> yuko さん
> 週末パワーでも太刀打ちならずでしたか…。
かなりの時間を費やしてしまい、後に引けない状態になっていますが、ひとまず終了ということで自分に言い聞かせています。
でも、やっぱり「なんで動かないのか?」が気になって、結局ちょこちょこ調査しちゃってます。もう、これって完全に沼…🫠
> 動作がちょっと心配なら、「マクロ → マクロ」はいいけど、「マクロ → マクロ → さらにマクロ」はできないように塞いでしまうのも一案かもしれませんね。
それだと負けた気が…😏 でも試しに「マクロ → マクロ (自分)」をやってみたところ、案の定、無限ループでフリーズしましたw
自分を呼び出す場合に限らず、「マクロ (1) → マクロ (2) → マクロ (1)」みたいなケースもあり得るので、再帰呼び出しを防ぐ仕組みを入れたほうがよさそうですね。
> あまり用途は考えられないものの、もしも複数回のエンジン切り替えが必要な場面があったら多層呼び出しにならないように「メインロジック (JScript) -> サブロジック (V8) 呼び出し -> 処理が戻ってきたことを確認 -> サブロジック (QuckJS) 呼び出し」とかマクロの作りですればいい気がします。あ、でもそういうの考えるとサブロジックから戻り値を受け取りたくなったりするのかしら…🤔
難しいですね。同じ JavaScript とはいえ、それぞれエンジンが異なるので、直接変数を受け渡すことはできません。もちろん、サブロジックが終了した時点でそのスクリプトエンジン自体も終了しているので、戻り値を取得するのも難しく…
変数の受け渡しは
Tagプロパティを使うくらいしか手がなさそうです😅>> enaka さん
> より簡単なTinyUVライブラリから調べるとよいかも。以下wikiがわかりやすい。
情報ありがとうございます。これは面白そうですね。
あれから
libuvのソースコードを読んでいたのですが、TinyUV はlibuvの機能を限定したバージョンっぽいので、より読みやすそうです。> 個人的に、非同期通信ならMQTTプロトコルとか喋れると面白いことが出来るかな、と思っています。
MQTT は初めて聞きましたが、確かに色々と面白いことができそうですね。組み込み用途だと、私は Arduino くらいしか触ったことがありませんが、情報も結構あるみたいで興味深いです。
> libtuvつながりでSamsungがTizenOSのために作ったJavascript Engine、JerryScriptがとても小さくていい感じ。
JerryScript、名前だけ知っていましたが、TizenOS 向けに作られたものだったんですね。
軽量な JavaScript エンジンを探していたので、これは良い情報です!
…とはいえ、試しに JerryScript をビルドしてみようとしたのですが、コンパイルが通らず…。Windows ではまだ微妙なのかもしれませんね。
> QuickJS以外にJavascript Engineを結構いろいろ見つけました。
QuickJS 以外にも色々あるんですね。リンク先もチェックしてみます!
| Kuro | 返信 -
> …とはいえ、試しに JerryScript をビルドしてみようとしたのですが、コンパイルが通らず…。Windows ではまだ微妙なのかもしれませんね。
ECMA script 5.1準拠と少し古いですがWindowsに移植されたものもあるようです。
https://github.com/LighteningZero/jerryscript-for-windows本家開発版はECMA2025に7割ほど準拠らしいですが、ECMA6にどこまで対応しているんだろう。
自社の家電製品で使用するためか、コンパクトさと安定性重視で着々と開発が進んでいる感じですね。| enaka | 返信 -
> でも、やっぱり「なんで動かないのか?」が気になって、結局ちょこちょこ調査しちゃってます。もう、これって完全に沼…🫠
何やらいけそうでいけない感じから、そのうちどこかでブレークスルーは起きそうですが…そんな状況で諦めるのもまた難しいの、分かります😂早く解決策が見つかりますように。
> 変数の受け渡しは`Tag`プロパティを使うくらいしか手がなさそうです😅
あ、なるほどその手が!であれば、どうとでもなりそうですね。
> 自社の家電製品で使用するためか、コンパクトさと安定性重視で着々と開発が進んでいる感じですね。
ほえー、組み込み向けのJavaScriptの着想は、いろいろなところであったんですねぇ…
| yuko | 返信 -
> …とはいえ、試しに JerryScript をビルドしてみようとしたのですが、コンパイルが通らず…。Windows ではまだ微妙なのかもしれませんね。
MSYS2環境でビルドをしてみましたが、最新のv3.0.0はリンクに失敗してしまいましたが、ひとつ前のv2.4.0では何もせずに素直にビルドできました。
~/tmp/jerryscript-2.4.0 $ ls -l ./build/bin/jerry.exe
-rwxr-xr-x 1 enaka None 400896 Mar 5 22:44 ./build/bin/jerry.exeファイルサイズは思ってたより大きいが、使用メモリはプロンプトで0.8MByteもいかない。
v3.0.0も少しヘッダファイル周りを直せばビルドできそうな気がする。> ほえー、組み込み向けのJavaScriptの着想は、いろいろなところであったんですねぇ…
Galaxy Watchで使われているそうです。
| enaka | 返信 -
> MSYS2環境でビルドをしてみましたが、最新のv3.0.0はリンクに失敗してしまいましたが、ひとつ前のv2.4.0では何もせずに素直にビルドできました。
MSYS2環境のucrt64-gccでWindowsネイティブにビルドしたら、最新のv3.0.0でも何もせずに素直にビルドできました。
逆にv2.4.0はWindowsネイティブにビルドできませんでした。
ただし、ビルドにはWindowsネイティブの /ucrt64/bin/python ではなく、MSYS2環境の /usr/bin/python を使う必要がありました。
また、ダウンロードしたアーカイブファイルに前回ビルドした際の環境依存のごみが含まれているのか、 --cleanオプションが必要でした。以下、作業内容です。
~/tmp $ wget https://github.com/jerryscript-project/jerryscript/archive/refs/tags/v2.4.0.tar.gz
~/tmp $ tar zxvf v2.4.0.tar.gz
~/tmp $ cd jerryscript-2.4.0
~/tmp/jerryscript-2.4.0 $ /usr/bin/python tools/build.py --clean
:中略
~/tmp/jerryscript-2.4.0 $ ls -l build/bin/jerry.exe
-rwxr-xr-x 1 enaka None 400896 2025-03-05 23:31 build/bin/jerry.exe
~/tmp/jerryscript-2.4.0 $ ldd build/bin/jerry.exe
ntdll.dll => /win/SYSTEM32/ntdll.dll (0x7ff9e4030000)
KERNEL32.DLL => /win/System32/KERNEL32.DLL (0x7ff9e39e0000)
KERNELBASE.dll => /win/System32/KERNELBASE.dll (0x7ff9e1ab0000)
msys-2.0.dll => /usr/bin/msys-2.0.dll (0x180040000)~/tmp $ wget https://github.com/jerryscript-project/jerryscript/archive/refs/tags/v3.0.0.tar.gz
~/tmp $ tar zxvf v3.0.0.tar.gz
~/tmp $ cd jerryscript-3.0.0
~/tmp/jerryscript-3.0.0 $ export PATH=/ucrt64/bin:$PATH
~/tmp/jerryscript-3.0.0 $ /usr/bin/python tools/build.py --clean
:中略
~/tmp/jerryscript-3.0.0 $ ls -l build/bin/jerry.exe
-rwxr-xr-x 1 enaka None 442368 2025-03-05 23:36 build/bin/jerry.exe
~/tmp/jerryscript-3.0.0 $ ldd build/bin/jerry.exe
ntdll.dll => /win/SYSTEM32/ntdll.dll (0x7ff9e4030000)
KERNEL32.DLL => /win/System32/KERNEL32.DLL (0x7ff9e39e0000)
KERNELBASE.dll => /win/System32/KERNELBASE.dll (0x7ff9e1ab0000)
ucrtbase.dll => /win/System32/ucrtbase.dll (0x7ff9e1920000)| enaka | 返信 -
>> enaka さん
情報ありがとうございます。
v2.4.0 が見つからないな~と思っていたら、私が試していたのは Jerryscript for Windows のほうでした。
本家のほうはビルドできるんですね。
せっかくなので v2.4.0 をビルドしてみようと思って、CMake に対応してそうだったから「Visual Studio でもいけるかな?」と試してみたのですが、リンクエラーが発生…
で、教えていただいた手順どおりに MSYS2 でやってみたのですが、私の環境だとエラーでビルドできませんでした。
jerry-core/CMakeFiles/jerry-core.dir/compiler_depend.make:4: *** multiple target patterns. Stop. make[1]: *** [CMakeFiles/Makefile2:207: jerry-core/CMakeFiles/jerry-core.dir/all] Error 2 make: *** [Makefile:136: all] Error 2 ============================== Build failed with exit code: 2 ==============================もう、何のエラーなのかサッパリ…🤷♂️
MSYS2 は、ついこの前 yuko さんに教えてもらったばっかりで、まだ勝手がよく分かってなくて…。せっかく情報いただいたのに、すみません。
> -rwxr-xr-x 1 enaka None 400896 Mar 5 22:44 ./build/bin/jerry.exe
おお、400KB くらいですか。QuickJS が 700KB くらいで軽いな~と思っていたのですが、さらにコンパクトとは…さすが組み込み向けですね。
オプションに共有ライブラリ (たぶん DLL?) もあったので、Delphi から使えたりするかな?と思ったのですが、Delphi 関連の情報がまったく見つからず…。Mery で使うには、なかなかハードル高そうですね~ ^^;
| Kuro | 返信 -
ビルドするターゲットのコンパイラが見つけられていないみたいです。
> MSYS2 は、ついこの前 yuko さんに教えてもらったばっかりで、まだ勝手がよく分かってなくて…。せっかく情報いただいたのに、すみません。
自分が入れたMSYS2のパッケージは以下で芋づる式に入ったものですが、半分以上いらないと思います。
~ $ cat SetupFiles/msys2_setup.sh
#!/bin/shpacman -Syyuu --noconfirm
pacman -S --noconfirm autogen autotools bison bc bsdcpio clang cmake cmatrix cpio cvs cygutils diffutils docx2txt dos2unix ed emacs fish flex gcc git lftp lz4 lzip lzop m4 make man2html man-db mc moreutils nasm nawk openssh p7zip pacutils patch patchutils python-pip rcs subversion tcsh txt2html txt2tags tmux tree unrar unzip vim w3m whois winpty yasm zip zsh
pacman -S --noconfirm mingw-w64-ucrt-x86_64-bat mingw-w64-ucrt-x86_64-emacs mingw-w64-ucrt-x86_64-eza mingw-w64-ucrt-x86_64-ffmpeg mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-ghostscript mingw-w64-ucrt-x86_64-go mingw-w64-ucrt-x86_64-jq mingw-w64-ucrt-x86_64-micro mingw-w64-ucrt-x86_64-rust mingw-w64-ucrt-x86_64-yt-dlp
pacman -Sc --noconfirm
> オプションに共有ライブラリ (たぶん DLL?) もあったので、Delphi から使えたりするかな?と思ったのですが、Delphi 関連の情報がまったく見つからず…。Mery で使うには、なかなかハードル高そうですね~ ^^;
以下をONにすると残念ながらV3.0.0とV2.4.0ともコンパイルエラーになりました。?がついているので作業中なのかもしれません。
~/tmp/jerryscript-2.4.0 $ nano CMakeLists.txt
:中略
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries?")
:| enaka | 返信 -
v3.0.0のWindowsネイティブバイナリがビルド出来ているので不要かとも思うのですが、v2.4.0のWindowsネイティブバイナリもビルド出来るようになりました。
v2.4.0のバグだったため、以下、3か所にパッチを当てる必要があります。~/tmp $ cat jerryscript-2.4.0.patch
diff -rN jerryscript-2.4.0.orig/jerry-core/ecma/base/ecma-helpers-string.c jerryscript-2.4.0/jerry-core/ecma/base/ecma-helpers-string.c
1804c1804,1805
< lit_utf8_size_t string1_size_and_length[2], string2_size_and_length[2];
---
> lit_utf8_size_t string1_size_and_length[2] = { 0 };
> lit_utf8_size_t string2_size_and_length[2] = { 0 };
diff -rN jerryscript-2.4.0.orig/jerry-ext/handle-scope/handle-scope-allocator.c jerryscript-2.4.0/jerry-ext/handle-scope/handle-scope-allocator.c
129c129
< long idx = JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope);
---
> ptrdiff_t idx = JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope);
diff -rN jerryscript-2.4.0.orig/jerry-port/default/default-module.c jerryscript-2.4.0/jerry-port/default/default-module.c
130c130
< const size_t drive_len = strnlen (&drive, _MAX_DRIVE);
---
> const size_t drive_len = strnlen (drive, _MAX_DRIVE);>オプションに共有ライブラリ (たぶん DLL?) もあったので、Delphi から使えたりするかな?と思ったのですが、Delphi 関連の情報がまったく見つからず…。Mery で使うには、なかなかハードル高そうですね~ ^^;
Win32でもDLLをビルド出来た方もいるようです。
https://github.com/BernardXiong/jerryscript_win32出来る見込みはありそうなので引き続き、v3.0.0のMSYS2バイナリがリンクに失敗してビルドできない件と、共有ライブラリのダイナミックリンクがビルドできない件を調査中です。
参考にWSL2 Debianでビルドしたところ、共有ライブラリのダイナミックリンクでもビルド出来ました。おまけ1
v3.0.0にスタックオーバーフローのセキュリティホールが見つかってる orz
https://nvd.nist.gov/vuln/detail/CVE-2022-22893おまけ2
DelphiからJerryScriptを使う方法を探していたら、ご存じかもしれませんがChakraCoreを直接使う方法を見つけました。
https://github.com/tondrej/chakracore-delphi
https://github.com/hsreina/ChakraCore-DelphiそういえばChakraCoreもオープンソースになっていたんでしたね。jscript9.dllが終了しても最悪なんとかなるのか。
| enaka | 返信 -
>> enaka さん
情報ありがとうございます。
教えていただいた手順でコンパイラ周りをインストールしたところ、無事 v3.0.0 のビルドに成功しました。
さっそく、yuko さんからいただいたベンチマークのコードを
jerry.exeで実行してみました。# JerryScript (jerry.exe 64 ビット版) 5306.00ms 5298.00ms 5296.00ms 使用メモリ: 0.3 MB# QuickJS-NG (qjs.exe 64 ビット版) 2767.00ms 2762.00ms 2757.00ms 使用メモリ: 0.8 MBJerryScript は、確かにメモリ使用量が少ないですね。さすが小型デバイス向け。実行ファイルのサイズが小さいことも影響しているのかもしれませんが。
ただ、実行速度は QuickJS のほうが速くて、JerryScript は JSCRIPT9LEGACY.dll と同じくらいのパフォーマンスみたいですね。
> Win32でもDLLをビルド出来た方もいるようです。
> https://github.com/BernardXiong/jerryscript_win32おぉ…、見てみたら最終更新が 7 年前…
ビルド済みの DLL も含まれていたので関数をダンプしてみたところ、libengine.dll が JerryScript の本体っぽいですね。
エクスポート関数があるせいか、ファイルサイズは 873 KB と、ちょっと大きくなっていました。
> おまけ1
> v3.0.0にスタックオーバーフローのセキュリティホールが見つかってる orz
> https://nvd.nist.gov/vuln/detail/CVE-2022-22893おうふ…。まあ、これはどんなアプリでも起こり得ることなので、仕方ないですね。
> おまけ2
> DelphiからJerryScriptを使う方法を探していたら、ご存じかもしれませんがChakraCoreを直接使う方法を見つけました。
> https://github.com/tondrej/chakracore-delphi
> https://github.com/hsreina/ChakraCore-DelphiChakraCore (というか当時は chakra.dll) は、Mery で JScript9 の Chakra (jscript9.dll) に対応するときに調べたことがありました。
でも、chakra.dll を直接呼ぶのは難易度が高すぎて断念。結局、ActiveScript で実装できる JScript9 の Chakra を採用しました。
> そういえばChakraCoreもオープンソースになっていたんでしたね。jscript9.dllが終了しても最悪なんとかなるのか。
そうですね。本家の Chakra はマイクロソフトのサポートが終わっているので、いつ消滅するかわかりません。自前でビルドしてアプリに同梱するなら配布は可能かもしれませんが…
とはいえ、サイズが 6 MB (Windows に入ってる chakra.dll) くらいあるので、軽量とは言いがたいですね。
それでも V8 ほどではなさそうなので、試しに ChakraCore をビルドしてみようとしたら、エラーが多発してビルドできず。
Visual Studio 2015 or 2017と書かれているので、2022 だとダメなのかしら。でも、今さら 2015 や 2017 を入れるのは気が進まないですね😅しかも、オープンソース化されたとはいえ、ほぼ放置状態っぽいです。
Latest リリースが 2020 年のままで、新機能の追加もなし。セキュリティ面を考えると、長期的に使うのはリスクありそうですね。
| Kuro | 返信 -
>> yuko さん
フォーラムのテキストエリアに
MarkdownEditorLikeTextarea.jsを組み込ませていただきました!いい感じに動いています😊> 末尾あたりにあるような感じで、「インスタンス化 → enable()」とすると動くはずです。
const target = document.querySelector('textarea'); const mdTextarea = new MDTextarea(target); mdTextarea.enable();これ、特に記述しなくても、
<script>で組み込むだけで自動適用されるんですね。本体のコードを読まずに、言われたとおりにコピペしていたらエラーが出て、ちょっと焦りましたが、無事導入できました。
インデント機能や「・」でのリスト編集も便利そうなので、マークダウンの有効/無効に関係なく適用しています。(というより、自動適用されてますねw)
特にリスト編集は Word などと操作感が同じなので、初心者さんにも使いやすそうです。素敵なスクリプトをありがとうございます😉
| Kuro | 返信 -
> フォーラムのテキストエリアに`MarkdownEditorLikeTextarea.js`を組み込ませていただきました!いい感じに動いています😊
おおっ、採用ありがとうございます!このメッセージはAndroidスマホから書いているのですが、ちゃんと想定の動きをしていますね。
> これ、特に記述しなくても、`<script>`で組み込むだけで自動適用されるんですね。
丸っとコピペですと、無名関数で宣言して即時呼び出しをしているので、そんな動きになりますね。
ちなみにクラス部分だけをコピーしてインスタンス化時の引数を調整して有効化すると、 発動タイミングを調整したり、shift+enter で改行するときに発動することができたりなど、簡易的なショートカット変更ができたりします。元々はPerplexityの検索ボックスの改行 (shift+enter) で使いたくって作ったものだったので、そんな選択肢を用意してみました。
そして、これを組み込んでPerplexityをカスタムするChrome拡張機能を作ってみたのがこちら:
chromewebstore.google.com/detail/perplexity-mini-tools/dniomjbkoibfmmdjeghickikhdlddhnm| yuko | 返信 -
> おおっ、採用ありがとうございます!このメッセージはAndroidスマホから書いているのですが、ちゃんと想定の動きをしていますね。
スマホでもちゃんと動いているとのことで安心しました!…私はフリック入力ができない世代でして (というか、いまだにガラケー愛用中)、そもそもスマホで文章を書ける時点で凄いと思います😅
> ちなみにクラス部分だけをコピーしてインスタンス化時の引数を調整して有効化すると、 発動タイミングを調整したり、shift+enter で改行するときに発動することができたりなど、簡易的なショートカット変更ができたりします。
なるほど。もし「デフォルトではオフにしてほしい」といったご意見があれば、その仕組みも参考にさせていただきますね。
> そして、これを組み込んでPerplexityをカスタムするChrome拡張機能を作ってみたのがこちら:
> chromewebstore.google.com/detail/perplexity-mini-tools/dniomjbkoibfmmdjeghickikhdlddhnmおおー、Chrome の拡張機能まで作れるとは凄すぎます!しかも Mermaid にも対応しているとは…
Perplexity は気になっているのですが、実はまだ ChatGPT を使い続けていまして。そのときが来たら導入させていただきますね。
生成 AI といえば、Google AI Studio で Gemini を使って、Mery の CHANGELOG やブログ記事、マイクロソフトの文章規約、Mery のソースコードなどを学習させて Mery のドキュメントを書いていたのですが…
チャットのログが増えすぎて重くなってきたので、いったんクリアしてみたら、今まで覚えたことがぜーんぶー消えてしまいました\(^o^)/オワタ🐥
さらに雑談ですが…、QuickJS の fetch (libuv が動かない問題) に心を折られて以来、モチベーションが下がってしまいまして…
で、今日は昼寝していたら、夢の中で Mery の正規表現の置換を高速化する方法を思いついたので、そちらをやっているところです。
そんなわけで QuickJS の進捗は今のところありませんが、正規表現の折り返しまたぎにも関連する話なので、改めて例のトピックのほうで共有させていただくかもしれません。 (RegExMode=2 の挙動に関する追加仕様もあるので…)
【参考】編集モードで折り返し時、3行目から意図した色にならない
https://www.haijin-boys.com/discussions/8738そのときは、検証にご協力いただけると嬉しいです🙇♂️
| Kuro | 返信 -
> チャットのログが増えすぎて重くなってきたので、いったんクリアしてみたら、今まで覚えたことがぜーんぶー消えてしまいました\(^o^)/オワタ🐥
あぼーん…(死語)
> さらに雑談ですが…、QuickJS の fetch (libuv が動かない問題) に心を折られて以来、モチベーションが下がってしまいまして…
ありゃ、そうでしたか。
QuickJSは楽しみですが、ゆっくりとお待ちしていますね。> で、今日は昼寝していたら、夢の中で Mery の正規表現の置換を高速化する方法を思いついたので、そちらをやっているところです。
またも夢駆動開発ですねw 公開されたら試させていただきますね😉
| yuko | 返信 -
ご返信ありがとうございます。
> QuickJSは楽しみですが、ゆっくりとお待ちしていますね。
いや~、なかなか大変なことになっていますね…。なんとか進めてはいるものの、新たな壁が現れてしまいました…😇
以前のこの発言ですが、
> 変数の受け渡しはTagプロパティを使うくらいしか手がなさそうです😅
Tag プロパティの仕様はすっかり忘れていて、「まあ、なんでも入れられる万能プロパティでしょ?」くらいに思っていたのですが、いざソースコードを見てみたら衝撃。
Scripting.Dictionaryを使ってるじゃないですか。これって ActiveX オブジェクトなので、QuickJS とは互換性がなく、Tag プロパティ経由での変数のやりとりはできませんでした🙇♂️
しかも、QuickJS の変数はそもそも COM 規格とはまったく別の仕組みなので、仮に Tag が使えたとしても、受け渡し自体がかなり厳しそうです。
ただ、問題はそこではなく… ActiveX オブジェクトの存在。
Scripting.Dictionaryはおそらく VBScript のコンポーネントなので、VBScript が廃止されたら、Tag プロパティ自体が使えなくなるかもしれません…😱そこで、とりあえずの妥協案として考えたのが、
TagStringというシンプルな文字列型のプロパティを追加する方法です。従来の
TagはDictionary型で、キー + 自由な型 (Variant)の組み合わせで、文字列・数値・配列・オブジェクトなど、何でも格納できました。でも、
Dictionary型や配列、オブジェクトは QuickJS との互換性がないんですよね…そこで、
Tagプロパティは ActiveX が廃止されるまでは下位互換として残す- 新しく
TagStringプロパティを追加して、シンプルな文字列型のみを扱うようにする
こうすれば、文字列型であれば V8 や QuickJS との互換性も確保できます。もし配列を保存したい場合は、JSON.stringify して保存・取得すれば OK です。
ただ、問題点として…
- 既存のマクロとの互換性が失われる
- シンプルな文字列型だと、他のユーザーが作成したマクロに上書きされる可能性がある
特に後者が悩ましいんですよね…
Scripting.Dictionaryを採用した理由の一つは、Tag プロパティが自由に書き換えられることで、他のマクロによって意図せず上書きされるリスクを防ぐためでした。【参考】マクロ用の変数の要望
https://www.haijin-boys.com/discussions/3418その点を考えると、
TagStringのような自由に書き換え可能なプロパティは、当初のポリシーに反してしまいます。とはいえ、VBScript が廃止されて Tag プロパティが使えなくなるとなると、QuickJS との受け渡し以前に、代替手段を考えないといけない状況です…
できれば、QuickJS と互換性があり、さらに既存のマクロの書き換えも最小限に抑えられる方法があればいいのですが🫠
| Kuro | 返信 -
TagStringもTagと同じくkeyとvalueでデータを保持するのでいいんですかね?
単純な方法としては実際のkeyをマクロから渡されたkeyにテキストファイルのパスとかマクロファイルのパスなどと組み合わせて、さらにハッシュ関数で変換したものにするとか。| barrackdo | 返信 -
> TagStringもTagと同じくkeyとvalueでデータを保持するのでいいんですかね?
いえ、そうではなく、
Tagプロパティでkeyとvalueを使ってデータを保持できていたのは、ActiveX のScripting.Dictionaryを使っていたからなんです。【参考】【VBScript】連想配列について
https://qiita.com/mihooo24/items/1357cd9b34d8e0e91777VBScript が廃止されて
Scripting.Dictionaryが使えなくなると、keyとvalueでデータを保持する仕組みそのものがなくなってしまうんですよね。それで今、どうしようか悩んでるところです。
なので、
Scripting.Dictionaryに依存しない仕組みとして、TagStringはkeyとvalueではなく、単純な文字列型の一時的な変数置き場として用意するのはどうかな~と思っていたのですが…これだと、他のマクロに上書きされるリスクがあるので、ちょっと微妙そうなんですよね。
最終手段として、
Scripting.Dictionaryを自前でゼロから作るという力技は残されていますが…😱その後、調べていたら、Mac 版の Excel では、もちろん ActiveX の
Scripting.Dictionaryは使えませんが、代わりの互換品を作っている方がいたので、少し可能性が見えてきました。【参考】VBA-Dictionary
https://github.com/VBA-tools/VBA-Dictionaryこれを Delphi で実現できれば…って、テキストエディターの開発からだいぶ脱線してきましたね…😮💨 (次のバージョン作らねば…)
| Kuro | 返信 -
>
Tagプロパティでkeyとvalueを使ってデータを保持できていたのは、ActiveX のScripting.Dictionaryを使っていたからなんです。Scripting.Dictionary、久々に聞きました。VBAやVBSで見るアレですね。Tagプロパティ、よくわからないけどexistsメソッドとか使えるなぁとあまり意識せず使っていたんですが、なるほど、それもScripting.Dictionaryに含まれる関数だったということなんですね。となると代替方法はたしかに悩ましいですね…🤔
私としては、おっしゃるようにJSON Stringにでも変換してしまえばいいので格納できる値は文字列型だけでも十分なのですが、やっぱりキーが扱えないのは意図せず他マクロの値を上書きしてしまいそうで、ちょっと痛いところです。
例えばですが、プロパティではなくメソッドでタグの読み書きを用意するとかだとどうでしょうか?そしてメソッドによりセットされた key-value は、Delphi上ではdocument毎 or window毎に1つのハッシュテーブルで保持できないでしょうか。
マクロ上では以下のように呼び出すイメージです。
// タグ値のセット document.setTag('tag-name', 'tag-value'); // タグ値の取得 var tagValue = document.getTag('tag-name'); // タグの存在確認 (戻り値 true/false) var isExists = document.tagExists('tag-name');| yuko | 返信 -
> Tag プロパティ、よくわからないけど exists メソッドとか使えるなぁとあまり意識せず使っていたんですが、なるほど、それも Scripting.Dictionary に含まれる関数だったということなんですね。
そうなんです。しかも
Scripting.Dictionaryって、JScript だとdocument.Tag("Key1") = "Value1";みたいに、関数の戻り値に対して値を入れるという妙な書き方をするんですよね。(JavaScript 的にアウトじゃないのかしら?)
で、V8 だとこの書き方はエラーになるみたいで、
document.Tag["Key1"] = "Value1";のように、プロパティでアクセスするかたちになってるみたいですね。って、yuko さんのマクロを見て知ったのですが😅
> 例えばですが、プロパティではなくメソッドでタグの読み書きを用意するとかだとどうでしょうか?そしてメソッドによりセットされた key-value は、Delphi上ではdocument毎 or window毎に1つのハッシュテーブルで保持できないでしょうか。
そうですね。メソッド方式は、当時、Tag プロパティの実装を考えてたときに、私も提案していました。(先日、参考リンクを貼ったフォーラムでの [サクラエディタさん方式])
ただ、「Dictionary 型にしてほしい」というご要望があったことと、独自規格にしてしまうとユーザーさんの学習負担が増えるため、ネット上に情報の多い
Scripting.Dictionaryを採用したんですよね。(結果、実装に 2 年かかっていましたがw)とりあえず、
Scripting.Dictionaryの互換品の開発にチャレンジしてみて、それがダメならメソッド方式を検討する方向で…| Kuro | 返信 -
> document.Tag(“Key1”) = “Value1”;
これ、不思議ですよね…なにかJavaScript仕様の裏をかいた方法でセットしているんでしょうかね。V8のように
document.Tag["Key1"]の方が普通にオブジェクトを扱ってるって感じで分かりやすいと感じます。> とりあえず、
Scripting.Dictionaryの互換品の開発にチャレンジしてみて、それがダメならメソッド方式を検討する方向で…たしかに、今と同じ使い方でできたらそれに越したことはないですね。
| yuko | 返信 -
> V8のように document.Tag[“Key1”] の方が普通にオブジェクトを扱ってるって感じで分かりやすいと感じます。
ですです。これ、私がやったわけではなくて、おそらく
Scripting.Dictionaryの方で、Microsoft が新しい JavaScript 規格に合わせてメンテしているのだと思います。> たしかに、今と同じ使い方でできたらそれに越したことはないですね。
Tag プロパティは VBScript が終了するまで残しつつ、新しい Tag 的なプロパティを用意して時間稼ぎを…と、あんままままま、あまーいことを考えていましたが、行きますか、イバラの道を…🥹
って、QuickJS v0.9.0 がリリースされてるっ!めちゃくちゃ変更点が多いですね…。だいぶ実装を進めたところなのに、仕様変更とか勘弁してほしいなぁ…
| Kuro | 返信 -
> Tag プロパティは VBScript が終了するまで残しつつ、新しい Tag 的なプロパティを用意して時間稼ぎを…と、あんままままま、あまーいことを考えていましたが、行きますか、イバラの道を…🥹
相変わらず見守ることしかできませんが、応援しております!
> って、QuickJS v0.9.0 がリリースされてるっ!めちゃくちゃ変更点が多いですね…。だいぶ実装を進めたところなのに、仕様変更とか勘弁してほしいなぁ…
fixがマメに来るのは嬉しい反面、ライブラリ系のアップデートはビクビクしちゃいますね😅
ところで、v0.9.0 が来たこととは関係ないのですが、QuickJS版が来たらやりたいことが1つ見つかりました。 expr-eval を使った電卓マクロです。
今でも、マクロライブラリに掲載されている電卓マクロは便利に使わせていただいているのですが、最近見つけた expr-eval だと、扱える数式 (累乗の
^など) がよく見かける形式で扱えそうだなと眺めていました。現状、V8でも以下のような感じで使うことはできるのですが、これが起動時のリードタイム皆無で動作したら気持ちいいなぁと思いました。
<https://cdnjs.cloudflare.com/ajax/libs/expr-eval/2.0.2/bundle.min.js などから取得したコードを貼り付ける> function main() { // 上記貼り付けたコードからインスタンス化して使う var Parser = exprEval.Parser; alert(Parser.evaluate("2 ^ 3")); }| yuko | 返信 -
> 相変わらず見守ることしかできませんが、応援しております!
ありがとうございます!ただ、QuickJS についてはまだ時間がかかりそうなので、ひとまず Ver 3.7.13 のリリースを近日中に予定しています。
> fixがマメに来るのは嬉しい反面、ライブラリ系のアップデートはビクビクしちゃいますね😅
ですよね😅 公式サイトによると、平均 2 か月ごとに新しいリリースがあるとのことなので、これを追いかけるのはなかなか大変そうです…💦
> ところで、v0.9.0 が来たこととは関係ないのですが、QuickJS版が来たらやりたいことが1つ見つかりました。 expr-eval を使った電卓マクロです。
情報ありがとうございます!
いただいたコードを QuickJS で試してみたのですが、エラーで動作しませんでした。どうやら QuickJS では
selfが使えないようです。この程度なら Mery 側で実装できるので、修正して動作するようにしました。リードタイムはほぼゼロといったところですね。
ちなみに、私が気づいた点として、Mery に同梱しているマクロで使用している
RegExp.lastMatchも QuickJS では使えませんでした。そもそも
RegExp.lastMatchはすでに非推奨になっているようなので、使えなくても仕方ないのですが…ほかにも、MeryWiki のマクロ ライブラリからいくつか抜粋して QuickJS で動作チェックをしてみたのですが、ActiveX を使っているものなどがあり、なかなか適したサンプルを見つけるのが大変ですね。
バグ出しにもなるので、もし「このスクリプトを試してほしい」といったものがあれば、教えていただけると助かります😊
| Kuro | 返信 -
> この程度なら Mery 側で実装できるので、修正して動作するようにしました。リードタイムはほぼゼロといったところですね。
おおーっ、いけましたか。となると、ブラウザやNode.jsで使えるライブラリをMeryでV8を用いずに使えるものが増えるかもしれませんね!
> ちなみに、私が気づいた点として、Mery に同梱しているマクロで使用している
RegExp.lastMatchも QuickJS では使えませんでした。
> そもそもRegExp.lastMatchはすでに非推奨になっているようなので、使えなくても仕方ないのですが…うーん、やっぱりそういうのはチラホラ出てきそうですよね。まぁ言語仕様の変遷の影響を受けるのもまた
#languageのエンジン切り替えの特徴でしょうし、そこはある程度お察しくださいとしたいところではありますよね。しかしやはり、 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference に載っているような現代のJavaScript文法はJScriptだとやっぱり色々と動かないので、こういったメジャーなリファレンス通りに読み取ってくれるエンジンだとプログラミングはしやすくなるので良いですね☺️
> バグ出しにもなるので、もし「このスクリプトを試してほしい」といったものがあれば、教えていただけると助かります😊
前向きなサポートありがとうございます!
先日の expr-eval ですが、一応フル版でお渡ししておきますね。以下のようなマクロに組み込んで利用しています。
Mery 電卓あと、便利に使っていて、テキスト処理からちょっと道を外れたようなものでいうと以下のあたりですかね。いずれもActiveXObjectを使っているので、Meryのshellオブジェクトで代替できればいいけど…と思っているところです。
| yuko | 返信 -
> おおーっ、いけましたか。となると、ブラウザやNode.jsで使えるライブラリをMeryでV8を用いずに使えるものが増えるかもしれませんね!
それ、ほんと夢が広がりますね😊
そういえば、Node.js や V8 って初回起動時にネイティブコードにコンパイルする (JIT) ので、リードタイム的には QuickJS の方が有利っぽいですね。
ちなみに、Mery に QuickJS を実装したバージョンのリードタイムを計測してみたのですが、私の環境だと、マクロの初回起動時に 80 ミリ秒くらいかかりました。(dll から関数を読み込むので)
でも、2 回目以降は 0 秒で起動しますね。(Mery 側の機能を QuickJS に注入した状態で計測)
逆に、ベンチマークみたいな内部の処理速度としては V8 と比べると QuickJS のほうが不利ですが、マクロ用途だと瞬発力のある QuickJS のほうが向いてそうですね。
> こういったメジャーなリファレンス通りに読み取ってくれるエンジンだとプログラミングはしやすくなるので良いですね☺️
それはありますね。
classとかimportとか使えるのでワクワクしちゃいます。あ、そういえば、ひとつ、厳密になってるところがあって、たとえば、「CSV/TSV でアクティブ列選択」マクロだと、
menuTrack = menu.Track(0);みたいに変数を宣言せずにいきなり使うとエラーになるみたいです。こればっかりは Mery 側で吸収はできなさそうです。
でも、
var menuTrack = menu.Track(0);と直すだけで、他は修正なく動作しました。
> 先日の expr-eval ですが、一応フル版でお渡ししておきますね。以下のようなマクロに組み込んで利用しています。
> Mery 電卓情報ありがとうございます!
試してみたところ、このマクロはそのままで動作しました。V8 だともっさり感がありますが、QuickJS だとサクサク動きます👍
> あと、便利に使っていて、テキスト処理からちょっと道を外れたようなものでいうと以下のあたりですかね。
なるほど、しかし、ActiveX はちょっと…。でも、QuickJS に実装していた
Shellにバグがあったのを発見できたので、助かりました😅見た感じ、「パス・URLを開く コマンドを実行する」は
wshShell.Popupやfso.GetFile(doc.FullName).ParentFolderあたりが厳しそうなので、そっ閉じしましたが…w「開いている文書のファイル名を変更する」は
fsoをshellに書き換えるだけで動作しました。(このマクロ、便利ですね)Ver 3.7.13 もリリースできたので、これでようやく QuickJS に本腰を入れて取り組めそうです。次は Ver 3.8.0 でどどん!と行きたいですね😺
| Kuro | 返信 -
> でも、2 回目以降は 0 秒で起動しますね。(Mery 側の機能を QuickJS に注入した状態で計測)
おおーっ、80ミリ秒でもほとんど体感しなさそうですが、2回目以降はキャッシュされる感じなんですね。私のようにEnterキーすらマクロが動く環境にはめちゃくちゃ嬉しいですねw
> 逆に、ベンチマークみたいな内部の処理速度としては V8 と比べると QuickJS のほうが不利ですが、マクロ用途だと瞬発力のある QuickJS のほうが向いてそうですね。
まさしくバイクとスポーツカーみたいな構図ですね。ごく短距離なら馬力よりも走り出しの軽さがものを言うと。
新しいバージョンで実装していただいた別スクリプト呼び出しもありますし、重い処理の際にだけV8を引っ張り出してくるのもアリですね。
> 「開いている文書のファイル名を変更する」は`fso`を`shell`に書き換えるだけで動作しました。(このマクロ、便利ですね)
fso系はやっぱり鬼門ですよねー。幸いshellでも一部は代替可能とのことで、ありがたいです。
> Ver 3.7.13 もリリースできたので、これでようやく QuickJS に本腰を入れて取り組めそうです。次は Ver 3.8.0 でどどん!と行きたいですね😺
全力で応援します!
| yuko | 返信 -
おや、気づけば折り返しインデント機能に「箇条書きインデント」なるオプションが…?更新履歴に記載が無いかもです。
動作を見比べた感じ、行頭の数字が箇条書きっぽいか否かを判定する機能ですかね?
| yuko | 返信 -
> 新しいバージョンで実装していただいた別スクリプト呼び出しもありますし、重い処理の際にだけV8を引っ張り出してくるのもアリですね。
そうですね。その用途なら、
ExecuteMacroは、ファイルを指定して実行するだけでなく、文字列を直接渡して実行することもできるので、ご活用いただければと思います。editor.ExecuteMacro("alert('aaa');", meRunText | meMacroLangV8);> 全力で応援します!
ありがとうございます!あ、でも Ver 3.7 系でちょっと追加したい機能が出てきたので、Ver 3.7.13 で何かバグが出たら、Ver 3.7.14 まであるかもです😅
> おや、気づけば折り返しインデント機能に「箇条書きインデント」なるオプションが…?更新履歴に記載が無いかもです。
気付かれましたか…。これはもともと隠しオプションとして実装していたのですが、新たに設けた [タブ/インデント] カテゴリが余白たっぷりで寂しかったので、こっそり表に出してみました。
更新履歴に書いていないのは、説明が難しくて、うまくまとめられなかったからです🙇♂️
> 動作を見比べた感じ、行頭の数字が箇条書きっぽいか否かを判定する機能ですかね?
そうですね、そんな感じです。
折り返しインデントの [追加のインデント文字] に数字を設定している場合 (例:
123456789.) に、行頭に数字が来ると、それが箇条書きの番号なのか、本文の一部なのかを “ある程度” 認識してくれます。たとえば、
1. 1995年3月16日~みたいな書き方だと、
1はインデント文字、.もインデント文字、さらにその後の(半角スペース) もインデント文字…と判定されてしまいます。すると、その後に続く、
1995もインデント文字になってしまうわけですが、これをある程度、回避してくれる機能です。分かりづらいですよね😅 そのうち、ドキュメントなどで説明を書こうとは思っています。
【参考】【要望】折り返し行インデント
https://www.haijin-boys.com/discussions/2277#discussion-7556| Kuro | 返信 -
> すると、その後に続く、
1995もインデント文字になってしまうわけですが、これをある程度、回避してくれる機能です。解説ありがとうございます。ざっくりと理解しました。
いいですね。私もそのケースがあるので数字は登録しない方がいいか…とか思っていた一人なのでした。
あとは個人的に、設定したいけどできないケースとして、
[と]もありますね。これは、Markdown形式のチェックリスト- [ ] ...を想定して登録しようとしたものなのですが、ログファイルによっては[INFO] YYYY-MM-DD ....みたいな形式になっているものもチラホラあり、そうなると1文字目の[で折り返しインデントが発動してしまって、それが気になるので断念しました…😅(- [ ] )みたいに、括弧でグルーピングをできると嬉しいですが、やはりそれは難しいでしょうか?| yuko | 返信 -
> あとは個人的に、設定したいけどできないケースとして、 [ と ] もありますね。
確かに、そのケースには対応できませんね。
グルーピングのような構造を実装し、それを解析する仕組みを作り、さらに箇条書きインデントの計算に組み込むとなると、残念ながら私の技術では難しそうです。
ちなみに、この機能は秀丸エディタさんの [箇条書きへのインテリジェントな対応] という機能を参考にさせていただいたのですが、秀丸エディタさんでもさすがにそこまでは対応されていないようです。
グルーピングは厳しいとしても、もうちょっと賢い箇条書き判定のアルゴリズムが思いつけば何とかなるかも?と思ってソースコードを眺めてみたのですが、今のところ何も閃かず…😅
| Kuro | 返信 -
>> Kuroさん
> バグ出しにもなるので、もし「このスクリプトを試してほしい」といったものがあれば、教えていただけると助かります😊
下記のスクリプトは日常的に使用しているので、動作チェックをしてもらえると助かります。
| MSY-07 | 返信 -
ご協力ありがとうございます。
現在開発中の QuickJS 対応版で試してみたところ、「ファイルを比較」は ActiveXObject の
WScript.Shellが使われていますが、これを Mery のshellを使うように書き換えるぐらいの変更で大丈夫そうです。(MSY-07 さん版も同様ですね)「最新版を確認」は ActiveXObject の
WinHttp.WinHttpRequest.5.1が使われているので、残念ながら QuickJS では動作しませんでした。QuickJS には HTTP 通信の機能がないので、ネットワーク通信を使うマクロには対応できないですね。
| Kuro | 返信 -
スクリプトのご確認ありがとうございます。
> 現在開発中の QuickJS 対応版で試してみたところ、「ファイルを比較」は ActiveXObject の
WScript.Shellが使われていますが、これを Mery のshellを使うように書き換えるぐらいの変更で大丈夫そうです。(MSY-07 さん版も同様ですね)「ファイルを比較」は問題がなさそうで良かったです😊
> 「最新版を確認」は ActiveXObject の
WinHttp.WinHttpRequest.5.1が使われているので、残念ながら QuickJS では動作しませんでした。
>
> QuickJS には HTTP 通信の機能がないので、ネットワーク通信を使うマクロには対応できないですね。QuickJSにHTTP通信の機能がないのでは仕方がないですね😓
| MSY-07 | 返信 -
Ver 3.7.13 のリリースお疲れ様です。
さっそく
ExecuteMacroを使ってみたのですが、いくつか気になる点があったので報告します。
下記のように V8 として実行しているマクロから
ExecuteMacroで V8 としてマクロを実行しようとすると止まってしまうみたいです。この状態になるとマクロの停止も効かず Mery を終了してもプロセスが残ってしまいます。#language = "V8" Alert('1'); editor.ExecuteMacro("Alert('2');", meRunText | meMacroLangV8);
また
Redrawプロパティの値が実際と異なっているようです。下記のようにベースのマクロでRedraw = false;にした後にExecuteMacroでマクロを実行すると再描画は行われませんがRedrawプロパティの値がtrueになっています。改めてRedraw = true;を実行すると再描画が行われます。ここからベースのマクロに戻るとRedrawプロパティの値がfalseになっていますが再描画が行われます。Redraw = false; document.selection.Text = '1'; Alert(Redraw); editor.ExecuteMacro( "document.selection.Text = '2'; Alert(Redraw);" + "Redraw = true; Alert(Redraw);" , meRunText); document.selection.Text = '3'; Alert(Redraw);個人的には再描画の挙動はこのままで
Redrawプロパティの値に実際の挙動が反映されるのが自然と感じます。
あとこれは
ExecuteMacroとは直接関係ないのですが V8 マクロが遅くなったり止まってしまうことがありました。 MeryWiki に投稿したUnicode正規化マクロをテスト目的で複数個所選択して実行して気づいたのですが、以下のようなマクロでも再現しました。#language = "V8" const sel = document.selection; for (let index = 0; index < 10000; index++) { const pos = sel.GetActivePos(); } Alert('終了');自分の環境では、10000回くらいだと 3.7.12 では数秒で終わるのですが 3.7.13 だと止まってしまいます。この時なぜかメニューバーのメニューを何か表示させると動いてくれます。
リリース直後で心苦しいですがご確認いただけたらと思います。
【環境】
- Mery: 3.7.13 (x64)
- OS: Windows 10 (Version 22H2, OS Build 19045.5608, 64-bit Edition)
- WebView2 Runtime: 133.0.3065.92
| ucky | 返信 -
早速お試しいただき、そしてご報告もありがとうございます。
> 下記のように V8 として実行しているマクロからExecuteMacroで V8 としてマクロを実行しようとすると止まってしまうみたいです。
現象を確認しました。もともと、QuickJS から V8 マクロを起動するために用意した機能なので、V8 から V8 を呼び出すことまでは想定していませんでした。
それにしても、どうやら WebView2 は複数同時に起動できないみたいです。デバッグしてみたら、2 つ目の WebView2 は起動しても応答なし…。うーん、何かしら制限を入れるか、1 つの WebView2 エンジンを使い回す仕組みを考えないといけなさそうです。
なかなか手強そうですが、対策を検討してみますね。
> またRedrawプロパティの値が実際と異なっているようです。
なるほど、確かに…。今のところ、
ExecuteMacroはマクロエンジンをそのまま新しく起動しているだけなので、Redrawプロパティとかの共通化までは考えてなかったんですよね。エンジンをまたいで共通にするべきプロパティ、ほかにもありそうですね。ちょっと調べてみます。
> 自分の環境では、10000回くらいだと 3.7.12 では数秒で終わるのですが 3.7.13 だと止まってしまいます。
こちらも確認しました。完全に止まってしまっているわけではなく、処理速度が遅くなっている感じですね。
原因は、おそらく
KeepScrollPosを実装した影響です。このプロパティを
trueにすると、マクロ実行中でもスクロールができるようになるのですが、その処理を優先する仕様にしたせいで、マクロ側の動作が遅くなっちゃったみたいです。これについては、改めて検証して、動作速度が改善できないか探ってみますね。
> リリース直後で心苦しいですがご確認いただけたらと思います。
いえいえ、とんでもないです!むしろ、マクロの動作検証をしてもらえるのはすごく助かります。気付いたことがあれば、またぜひ教えてください。
| Kuro | 返信 -
> うーん、何かしら制限を入れるか、1 つの WebView2 エンジンを使い回す仕組みを考えないといけなさそうです。
試しに EmEditor さんの動作を確認してみたところ、やはり V8 エンジンを複数同時 (入れ子) に起動するのは無理っぽいですね。
同期マクロの場合は、「V8 の入れ子の問題が発生しました」というエラー (たぶん既知の例外) でマクロが止まりました。
非同期マクロの場合は、エラーは出ず、ExecuteMacro したものをキューに入れて、メインマクロが終わったあとに順番に実行する仕様みたいです。
V8 の入れ子ができないのは残念ですが、Mery でも似たような感じで対策するしかなさそうですね。
> エンジンをまたいで共通にするべきプロパティ、ほかにもありそうですね。ちょっと調べてみます。
ほかにも何かあるかなと思ってざっと調べてみたのですが、window オブジェクトに直接保持されているのは Redraw プロパティくらいでした。これは次のバージョンで対応しておきますね。
> 自分の環境では、10000回くらいだと 3.7.12 では数秒で終わるのですが 3.7.13 だと止まってしまいます。
これ、試しに EmEditor さんで同じ V8 マクロ (GetActivePos を GetActivePoingX に変更) を実行してみたら、同様に処理がかなり遅くなって、応答がなくなりますね。
とりあえず、この件は調整が難しそうなので、ひとまず Ver 3.7.12 の仕様に戻しておこうと思います。(別のところに影響が出るかもですが…💦)
| Kuro | 返信 -
> とりあえず、この件は調整が難しそうなので、ひとまず Ver 3.7.12 の仕様に戻しておこうと思います。(別のところに影響が出るかもですが…💦)
あらら、残念ですが、
KeepScrollPos廃止ですか…😭| yuko | 返信 -
> あらら、残念ですが、 KeepScrollPos 廃止ですか…😭
いいえ、そういうわけではなく、
KeepScrollPosのために割いていたスクロール処理のリソースを廃止するだけなので、KeepScrollPos自体は残ります。ただ、マクロの処理を優先するようになるので、スクロールの反応がちょっと鈍くなるかもですが…😅
| Kuro | 返信 -
> V8 の入れ子ができないのは残念ですが、Mery でも似たような感じで対策するしかなさそうですね。
残念ですが仕方ないですね。でも途中で V8 マクロを起動したいときは立ち上がりのラグを軽減したいといったケースが多そうなので V8 マクロから起動できなくても問題ないかもしれませんね。
> とりあえず、この件は調整が難しそうなので、ひとまず Ver 3.7.12 の仕様に戻しておこうと思います。(別のところに影響が出るかもですが…💦)
KeepScrollPos、スクロールのパフォーマンスが落ちるのは残念ですが廃止にならなくて良かったです。将来なにか対策が見つかるといいですね。
QuickJS の動作チェックもされてるようなので、役に立つか分かりませんが問題が起きたマクロをフルで載せておきます。
Normalize.js
#title = "Unicode正規化" const sel = document.selection; const selectForm = function() { const forms = { '正規化形式&C': 'NFC', '正規化形式&D': 'NFD', '正規化形式&KC': 'NFKC', '正規化形式&KD': 'NFKD', }; const popupMenu = CreatePopupMenu(); Object.keys(forms).forEach(function(item, index) { popupMenu.Add(item, ++index) }); popupMenu.Add('', 0, meMenuSeparator); popupMenu.Add('キャンセル', 0); return forms[ popupMenu.GetText(popupMenu.Track(mePosMouse)) ]; }; const normalize = function(form) { if (!/^NFK?[CD]$/.test(form)) { return; } const dTag = document.Tag; let selections = []; const selectionCount = sel.Count || 1; for (let index = 0; index < selectionCount; index++) { selections.push({ anchorPos: sel.GetAnchorPos(index), activePos: sel.GetActivePos(index) }); } BeginUndoGroup(); AddUndo(); dTag('UnicodeNormalization-form') = form; dTag('UnicodeNormalization-selections') = JSON.stringify(selections); editor.ExecuteMacro('NormalizeV8.js'); selections = JSON.parse(dTag('UnicodeNormalization-selections')); sel.SetActivePos(selections[selections.length - 1].anchorPos); sel.SetActivePos(selections[selections.length - 1].activePos, true); sel.AddPos( selections.map(function(selection) { return [selection.anchorPos, selection.activePos]; }) ); EndUndoGroup(); dTag.remove('UnicodeNormalization-form'); dTag.remove('UnicodeNormalization-selections'); }; const forms = { 'NormalizeNFC.js': 'NFC', 'NormalizeNFD.js': 'NFD', 'NormalizeNFKC.js': 'NFKC', 'NormalizeNFKD.js': 'NFKD', }; Redraw = false; if (sel.Mode === meModeBox) { sel.Mode = meModeMulti; } if (sel.IsEmpty) { if (Confirm('選択範囲が空です。すべて選択して実行しますか?')) { sel.SelectAll(); normalize(forms[ScriptName] || selectForm()); } } else { normalize(forms[ScriptName] || selectForm()); } Redraw = true;NormalizeV8.js
#language = "V8" const sel = document.selection; const dTag = document.Tag; const form = dTag['UnicodeNormalization-form']; const selections = JSON.parse(dTag['UnicodeNormalization-selections']); let offset = 0; for (const selection of selections) { selection.anchorPos += offset; selection.activePos += offset; sel.SetActivePos(selection.anchorPos); sel.SetActivePos(selection.activePos, true); sel.Text = sel.Text.normalize(form); const bottomPos = Math.max(sel.GetAnchorPos(), sel.GetActivePos()); if (selection.anchorPos < selection.activePos) { offset += bottomPos - selection.activePos; selection.activePos = bottomPos; } else if (selection.anchorPos > selection.activePos) { offset += bottomPos - selection.anchorPos; selection.anchorPos = bottomPos; } else { offset += bottomPos - selection.activePos; selection.anchorPos = selection.activePos = bottomPos; } } dTag['UnicodeNormalization-selections'] = JSON.stringify(selections);| ucky | 返信 -
> いいえ、そういうわけではなく、
KeepScrollPosのために割いていたスクロール処理のリソースを廃止するだけなので、KeepScrollPos自体は残ります。ひとまず安心しました☺️
アップデート後の対応にQuickJSにと何かとバタついていますが、それだけMeryが愛用されていることの証左ですね (Kuroさん的には ヒェーーー って感じでしょうけど😅)
| yuko | 返信 -
>> ucky さん
> 残念ですが仕方ないですね。でも途中で V8 マクロを起動したいときは立ち上がりのラグを軽減したいといったケースが多そうなので V8 マクロから起動できなくても問題ないかもしれませんね。
その後、どうにも諦めきれずに、「Delphi の最新版ならいけるんじゃね?」とインストールして、シンプルなフォームに最低限の WebView2 (TEdgeBrowser) を貼り付けて実験してみました。
結果は…やっぱりダメでした💦 WebView2 のスクリプトの中から呼び出された WebView2 は応答しませんね。
ただ、あらかじめ WebView2 を 2 つ用意しておけば、片方がスクリプトを実行中に、もう片方の WebView2 のスクリプトを手動で実行することはできました。
でも、スクリプトの中からもう片方のスクリプトを自動実行しようとすると、やっぱりダメでした😓
【参考】https://learn.microsoft.com/ja-jp/microsoft-edge/webview2/concepts/threading-model
WebView2 は、メッセージ ポンプを使用する UI スレッドに作成する必要があります。 すべてのコールバックはそのスレッドで行われ、WebView2 への要求はそのスレッドで行う必要があります。 別のスレッドから WebView2 を使用しても安全ではありません。
コールバックが呼ばれない理由はこれかも?
メインスレッドから呼び出しているのですが、入れ子になるとメインスレッド側が処理待ちの状態になってしまうため、WebView2 的には「メインスレッドが待機してるから、別のメッセージ処理はできませんよ~」っていう状態になっている…という解釈。(えー、そんなことあるの?)
しかし、これはもう WebView2 の仕様っぽいですね。今のところは、諦めるしかなさそうです。
> QuickJS の動作チェックもされてるようなので、役に立つか分かりませんが問題が起きたマクロをフルで載せておきます。
おおー、ありがとうございます!このマクロ、めちゃくちゃ助かりました!
おかげで、QuickJS の v0.8.0 から v0.9.0 への「いや、これ絶対気付かんやろ!」みたいなヤバい仕様変更を発見できました。(こんな変更してくるのか…QuickJS こわっ😱)
ちなみに、
NormalizeV8.jsは#language = "quickjs"に書き換えても、そのまま動きました。しかも、めっちゃ高速!>> yuko さん
> アップデート後の対応にQuickJSにと何かとバタついていますが、それだけMeryが愛用されていることの証左ですね (Kuroさん的には ヒェーーー って感じでしょうけど😅)
ほんとそれ。もうバタバタしててヤバいです💦
QuickJS のほうは進める時間がなかなか取れなくて、とりあえず Ver 3.7.14 はアリってことで、そちらの開発を優先することになりそうです…😭
| Kuro | 返信 -
> 「開いている文書のファイル名を変更する」は
fsoをshellに書き換えるだけで動作しました。(このマクロ、便利ですね)そういえば…と思い今更 TIPS ですが、このマクロ、Explorer と合わせる形で「F2」キーでショートカットキー設定をしておくと大変便利です!
| yuko | 返信 -
> そういえば…と思い今更 TIPS ですが、このマクロ、Explorer と合わせる形で「F2」キーでショートカットキー設定をしておくと大変便利です!
なるほど、F2 キーって、もはやその用途専用みたいな感じですし、アリですね👍
こちらは現在、V8 の入れ子と格闘中です。途中で入れ子の例外を発生させるにしても、なかなか大変で…。
V8 → V8 なら普通にキャッチできるのですが…
JScript → V8 → JScript → V8 とか、
V8 → JScript → JScript → V8 とか…。
入れ子の途中でエラーで止めても、親側はそのエラーを知らないわけで…。そんな状況で、予想以上の大幅改修が発生しています😭
あとは、地味に
Scripting.Dictionaryの互換品を開発中で、そこそこかたちになってきました。キーは文字列型しか受け付けられない仕様ですが、それ以外はほぼ
Scripting.Dictionaryと同等で、従来の書き方でそのまま、JScript からも QuickJS からも使えるシステムにできそうです。その他、若干の制限事項はありますが、今語ってもイメージが湧きにくいと思うので、それはまた QuickJS 実装後に…
| Kuro | 返信 -
JavaScriptエンジンとはまた違うものなのでQuickJSが一段落したであろうところで紹介しようと考えてたのですが別スレッドで話題に出てきたので…。
WASMでプラグインを作るという発想自体は数年前にはてなブックマークのホッテントリで実装してるのを見かけて、それから夢があるなと思ってたんですよね。(直接的には関係ないのでURLは割愛)
ただ、WASIはまだ若い技術で制限も多そうですよね。あと、WASIのバージョニング方針(?)がよく分からない。
例えば現在の最新版のリリース記事(Bytecode Alliance — WASI 0.2 Launched)には「Most immediately, what this means is that the WASI Subgroup officially says that the WASI 0.2 APIs are stable.」とかありますが、どう取るべきか。
果たして将来的にもこのAPIが安定し続けていると取っていいのか…。というわけ(?)で実装するのを決めた場合でもフルスクラッチはおすすめできないので「wasm プラグイン」とかで検索すると出てくるExtism(extism/extism:)なんかを間に挟むのがベターですかね。
用意されているSDKの言語も豊富なようですし。
しかしDelphi言語のSDKはないので結局C,C++用のものから移植しないといけないかもですが。| barrackdo | 返信 -
>> barrackdo さん
> WASMでプラグインを作るという発想自体は数年前にはてなブックマークのホッテントリで実装してるのを見かけて、それから夢があるなと思ってたんですよね。(直接的には関係ないのでURLは割愛)
確かに、WASI を使えば WASM で Mery のプラグインを作ることにも対応できそうな気はしますね。
> ただ、WASIはまだ若い技術で制限も多そうですよね。
> あと、WASIのバージョニング方針(?)がよく分からない。
> 果たして将来的にもこのAPIが安定し続けていると取っていいのか…。うーん…確かに、そういう話を聞くと、WASI ってまだまだ発展途上って感じがしますね。
> というわけ(?)で実装するのを決めた場合でもフルスクラッチはおすすめできないので「wasm プラグイン」とかで検索すると出てくるExtism(extism/extism:)なんかを間に挟むのがベターですかね。
情報ありがとうございます。技術的にはすごく面白そうですが…
そもそも Mery のプラグインって C++ や Delphi でネイティブに書けるので、「WASM + WASI」にすることで何かメリットがあるのか、ちょっと気になりますね。
「C++ プラグイン → Mery」だったものが、「C++ → WASM プラグイン → Mery」になったところで、できることが増えるわけでもないし、WASM が速いとはいえ、ネイティブコード以上の速度が出るわけでもないですし…
マクロみたいに JavaScript で書く場合なら、C++ や Delphi は使えないので WASM の出番もありそうですが、それ以外だとクロスプラットフォーム対応くらいでしょうか。
あとは、セキュリティ面で WASI がしっかりしてるなら、C++ プラグインを廃止して全部 WASI 経由にすれば、プラグインの安全性は上がるかも?っていうのはありそうですね。
とはいえ、現時点では Mery と組み合わせるというより、面白そうな技術なので、別のプロジェクトで使い道が見つかればいいなぁ、といった印象です。
| Kuro | 返信 -
大変な作業になってしまったようで……開発お疲れ様です。
マクロ、お役に立ててよかったです。動作チェックもありがとうございます。無事動いたようで安心しました。
もうお気づきかもしれませんが、
KeepScrollPosで取得できる値が設定されているものと逆になってるみたいですね。Alert(document.KeepScrollPos); // true document.KeepScrollPos = true; Alert(document.KeepScrollPos); // false document.KeepScrollPos = false; Alert(document.KeepScrollPos); // true| ucky | 返信 -
> 大変な作業になってしまったようで……開発お疲れ様です。
ありがとうございます!
今回は軽めの修正で Ver 3.7.14 を出すつもりだったのですが、思った以上にあれこれ膨らんでしまって、気づけばもう 30 項目近くに…
> マクロ、お役に立ててよかったです。動作チェックもありがとうございます。無事動いたようで安心しました。
あのマクロ、その後の QuickJS 対応作業でもめちゃくちゃ助かりました。
数値型の配列を JSON.stringify してから JSON.parse で戻す処理も、すごく良かったです。
その処理を通したときに、変数の型がぶっ飛ぶという QuickJS の謎仕様 (バグっぽい?) も発見しまして…
私ひとりでは気づけなかったと思うので、本当に助かりました。(qjs.exe でも再現するので、対応はちょっと検討中ですが…)
> もうお気づきかもしれませんが、KeepScrollPosで取得できる値が設定されているものと逆になってるみたいですね。
おぉ…これは気づいてなかったです。教えていただいて助かりました。
もともと KeepScrollPos は AutoScroll という名前で、false にするとスクロール位置を維持するという、今とは逆の仕様だった名残がそのまま残ってしまってたみたいです。
そんなこんなで、Ver 3.7.14 もようやく完成が見えてきました。
記事などの準備もあるので、もう少し時間はかかりそうですが、のんびりお待ちいただけたら嬉しいです。
| Kuro | 返信 -
> そんなこんなで、Ver 3.7.14 もようやく完成が見えてきました。
>
> 記事などの準備もあるので、もう少し時間はかかりそうですが、のんびりお待ちいただけたら嬉しいです。お、いよいよですね。楽しみにしています!
ちょっと私の方からもお知らせを。
先日フォーラムのtextareaタグに導入していただいたMDTextareaですが、「極端に長い1行があって折り返し行数が多くなった場合に改行時やインデント操作でスクロール位置がずれる」という問題があったため、更新しておきました。
https://gist.github.com/yuru7/1c72d92ade8a83bad5a3eea32f8f51e9| yuko | 返信 -
> お、いよいよですね。楽しみにしています!
ありがとうございます!現在、Ver 3.7.14 の最終チェックを進めつつ、記事も書いているところです。
…とはいえ、最終段階に入ると、どうしても気になるところが出てきちゃうんですよね😅
もう少しだけ時間がかかりそうです。
> 先日フォーラムのtextareaタグに導入していただいたMDTextareaですが、「極端に長い1行があって折り返し行数が多くなった場合に改行時やインデント操作でスクロール位置がずれる」という問題があったため、更新しておきました。
メンテお疲れ様です!そして、ご連絡いただきありがとうございます。
早速、新しいバージョンを適用させていただきました。
せっかくなので、ちょっとだけ小ネタを…
> グルーピングは厳しいとしても、もうちょっと賢い箇条書き判定のアルゴリズムが思いつけば何とかなるかも?と思ってソースコードを眺めてみたのですが、今のところ何も閃かず…😅
あの箇条書き判定のアルゴリズム、ちょっとだけ賢くなりまして…
Markdown のタスク リストに対応できるようになりました。どうぞお楽しみに😉
| Kuro | 返信 -
> あの箇条書き判定のアルゴリズム、ちょっとだけ賢くなりまして…
>
> Markdown のタスク リストに対応できるようになりました。どうぞお楽しみに😉!!! なんと!
「今回は軽めの修正で Ver 3.7.14 を出すつもりだったのですが、思った以上にあれこれ膨らんでしまって、気づけばもう 30 項目近くに」と仰っていたあたりで、なにかしらサプライズ修正がありそうな予感はありましたが、やっぱりwこれは、ますます楽しみになってきました。
| yuko | 返信 -
Ver 3.7.14 のリリースお疲れ様です。
マクロの editor.ExecuteMacro メソッドで V8 の呼び出しを入れ子にすると、エラーを返すように修正
エラーメッセージが表示されるのを確認しました。ただ、エラーメッセージの前に同じ文言のアラートが表示されるのは冗長な気もしますね……。
マクロの Redraw プロパティをスクリプトエンジン間で共通化
Redraw プロパティの共通化確認しました。実際の挙動と一致していてわかりやすくなりました。
V8 マクロの動作速度が低下していた問題を修正
Ver 3.7.12 と同等の速さになっているのを確認しました。
マクロの document.KeepScrollPos の取得時に値が逆になっていた問題を修正
修正されているのを確認しました。
ご対応いただきありがとうございます。
| ucky | 返信 -
ご確認いただきありがとうございます。
ひとまず、うまく動作しているようで安心しました。
> エラーメッセージが表示されるのを確認しました。ただ、エラーメッセージの前に同じ文言のアラートが表示されるのは冗長な気もしますね……。
そうなんですよね…。そこはちょっとご勘弁ください😅
V8 エンジンの入れ子パターンっていろいろあって、「V8 → JScript → V8」とか「V8 → V8」、「V8 → VBScript → V8」みたいな感じで、なかなか複雑なんです。
で、スクリプトエンジンや入れ子の状態によっては、ちゃんとしたエラーメッセージを拾えなくて、「例外が発生しました」みたいなざっくりしたやつしか出てこないこともあって…。
そのため、Mery 側で一度エラーを検出して、できるだけ分かりやすくユーザーにお知らせするようにしてる、というわけです。
その関係で、似たようなメッセージが連続して表示されてしまうことがあり、ちょっとわずらわしく感じられるかもしれませんが…
Mery 側のエラーメッセージと、スクリプトエンジン側からのメッセージは、それぞれ別の処理に基づくものという点をご理解いただけると幸いです。
| Kuro | 返信 -
> そのため、Mery 側で一度エラーを検出して、できるだけ分かりやすくユーザーにお知らせするようにしてる、というわけです。
なるほど、そういう意図があったんですね。このエラーは一度仕様と理解すればそう頻繁に遭遇しなそうなので、分かりやすさの方が重要ですね。
| ucky | 返信 -
ぐふっ…。Ver 3.7 系もだいぶ落ち着いてきたし、そろそろ Ver 3.8 系と QuickJS に手をつけるか~と思ったら、もう QuickJS v0.10.0 出てるじゃないですか!
まだ v0.9.0 の仕様変更に追いついてる途中なのに~。更新ペース速すぎですー😭
| Kuro | 返信 -
> ぐふっ…。Ver 3.7 系もだいぶ落ち着いてきたし、そろそろ Ver 3.8 系と QuickJS に手をつけるか~と思ったら、もう QuickJS v0.10.0 出てるじゃないですか!
2, 3ヶ月おきにちゃんとリリースされてくれるの、嬉しいやら大変やらで悲鳴があがってしまいますね😂
メジャーバージョンにもなれば、CurrentバージョンとPre-releaseバージョンとで分かれて更新頻度も落ち着いてくれそうな気もしますが、まだ先かしら…
| yuko | 返信 -
> ぐふっ…。Ver 3.7 系もだいぶ落ち着いてきたし、そろそろ Ver 3.8 系と QuickJS に手をつけるか~と思ったら、もう QuickJS v0.10.0 出てるじゃないですか!
>
> まだ v0.9.0 の仕様変更に追いついてる途中なのに~。更新ペース速すぎですー😭まだQuickJS-NGはプレビュー版だから更新ペースが速いんですかね。
であれば、QuickJS-NGが正式版になってからMeryに実装した方が良いのではないでしょうか。
あと、本家のQuickJSも4月26日に更新されたみたいですね。
| MSY-07 | 返信 -
>> yuko さん
> メジャーバージョンにもなれば、CurrentバージョンとPre-releaseバージョンとで分かれて更新頻度も落ち着いてくれそうな気もしますが、まだ先かしら…
ですよね〜。せめて大きな仕様変更がなければ助かるのですが、今回もなかなかの大型アップデートっぽくて…。
ちょっとでもバージョンを飛ばすと、あっという間に置いていかれそうな勢いです😮💨
>> MSY-07 さん
> まだQuickJS-NGはプレビュー版だから更新ペースが速いんですかね。
> であれば、QuickJS-NGが正式版になってからMeryに実装した方が良いのではないでしょうか。プレビュー版とは書かれていないので、おそらく正式版だと思うのですが、どうなんでしょうね。
公式サイトにも「2 か月ごとの安定したリリースペースを維持する」とありますし、活発な開発サイクルも、このプロジェクトの特徴のひとつなのかもしれません。
Mery に組み込むとしても、どこかで思い切って飛び乗らないと始まりませんし、終わりの見えない大縄跳びに飛び込むような感覚です…。
> あと、本家のQuickJSも4月26日に更新されたみたいですね。
そうみたいですね。本家のほうは 1 年以上ぶりの更新だったみたいで、あまりにも音沙汰がなさすぎて、逆にちょっと心配になるレベルですね😅
| Kuro | 返信 -
> Mery に組み込むとしても、どこかで思い切って飛び乗らないと始まりませんし、終わりの見えない大縄跳びに飛び込むような感覚です…。
大変だとは思いますが、楽しみに待っていますね😊
| MSY-07 | 返信 -
のーん!もう QuickJS NG v0.10.1 がリリースされちゃいました。
まだ v0.9.0 → v0.10.0 の仕様変更を確認している途中なのに…。
今回のリリースでは、それほど大きな仕様変更はなさそうですが、いやはや、ほんとに慌ただしいプロジェクトですなぁ😅
| Kuro | 返信 -
> 今回のリリースでは、それほど大きな仕様変更はなさそうですが、いやはや、ほんとに慌ただしいプロジェクトですなぁ😅
どこかで飛び乗らねば…と飛び乗ってやっとのこと半身入れた途端、また新しい車両になってしまうみたいな…
もちろん前バージョンのものでも作り込みが台無しになるってことはないのでしょうが、それでも実装後の確認量を考えると悩ましいですね~😅 「もうこのバージョンで凍結して組み込んじゃおうかなぁ…でもバグフィックスや新機能もあるからバージョン上げたいし…むむむ」な感じなのだと想像…。
| yuko | 返信 -
> もちろん前バージョンのものでも作り込みが台無しになるってことはないのでしょうが、それでも実装後の確認量を考えると悩ましいですね~😅 「もうこのバージョンで凍結して組み込んじゃおうかなぁ…でもバグフィックスや新機能もあるからバージョン上げたいし…むむむ」な感じなのだと想像…。
まさにその「むむむ…」状態です。
v0.9.0 → v0.10.0 では仕様変更が多すぎて、いきなりまったく動かなくなってしまいまして…🥶
おまけにビルドまで通らなくなってしまい、QuickJS のソースコードを直接修正するハメに。時間も手間もかかって、もう大変でした。
と思ったら、v0.10.1 でしれっと修正されていて、振り回されっぱなしw
そんなこんなしているうちに、Ver 3.7.15 でもいくつか不具合が出てきたようで、QuickJS の組み込み (Ver 3.8 系) には、まだちょっと着手できそうにありませんね。
というわけで、ひとまずは Ver 3.7.16 までアリの方向で、方針を転換させていただきたいと思います😅
| Kuro | 返信 -
> そんなこんなしているうちに、Ver 3.7.15 でもいくつか不具合が出てきたようで、QuickJS の組み込み (Ver 3.8 系) には、まだちょっと着手できそうにありませんね。
おおっ、薄々そんな気はしていましたが、 Ver 3.8 でQuickJS搭載を目論んでいたのですね。
Ver 3.7、早く抜けられるといいですねw ともあれ予定は未定ということで、ゆっくりとご対応くださいませ。| yuko | 返信 -
> Ver 3.7、早く抜けられるといいですねw ともあれ予定は未定ということで、ゆっくりとご対応くださいませ。
ありがとうございます!
Ver 3.8 系は Ver 3.7 系とは別で開発しているので、3.7 側で修正が入ると、それを 3.8 にマージして…と、なかなか面倒なことになってますw
それはさておき、QuickJS (NG) の v0.10.1 がビルドできたので、さっそく Mery に組み込んでベンチマークを取ってみました。
v0.9.0 に比べて 500ms くらい速くなってるみたいで、かなり最適化が進んでるっぽいですね😯
#language = "quickjs" // qjs.dll (v0.10.1, 64 ビット) 2508.00ms 2514.00ms 2518.00msそれと、QuickJS 対応の進捗ですが、今は従来のマクロとの互換性を高めるために、ActiveX (COM オブジェクト) と QuickJS をつなぐブリッジ機構を開発中です。
ActiveX 廃止に備えて QuickJS を導入してるのに、今度は ActiveX をどうにかして使えるようにするという、本末転倒感はありますが…😅
とはいえ、「ActiveX を廃止するとは言ったけど、COM オブジェクトを廃止するとは言ってないよね!」という希望的観測のもとで進めてます。
うまくいけば、QuickJS から
Msxml2.ServerXMLHTTPとかの COM オブジェクトも使えるようになるので、fetch の代わりとして使えるかも?って感じです。| Kuro | 返信 -
コツコツとメンテしていただいて、ご苦労さまです。
最近、Meryマクロで計算機を作っていたんですけれど、小数計算の精度がJavaScriptってやっぱりイマイチ…なんて思っていたんですが、QuickJSだったらBigDecimalが使えるとかで、電卓の大幅改善ができるかもと期待が高まってきました。
https://jessealama.net/decimals-in-quickjs/| yuko | 返信 -
っと思ったら、BigDecimalは、QuickJS-NGでは削除され、BigIntになっていたようですね。これで代用かな…🤔
https://github.com/quickjs-ng/quickjs/issues/17| yuko | 返信 -
> コツコツとメンテしていただいて、ご苦労さまです。
ありがとうございます。地味な更新が続いていますが、こうして声をかけてもらえると励みになります。
> っと思ったら、BigDecimalは、QuickJS-NGでは削除され、BigIntになっていたようですね。これで代用かな…🤔
そのあたり、あまり詳しくないもので、「BigInt って何?」という感じなのですが、手元の QuickJS-NG で試してみたところ、BigInt (お尻に n が付くやつ) はちゃんと使えるみたいです。
それにしても、「QuickJS 対応はいつになるの?」と思われてるかもしれませんね…😅 (ほんとは 10 月ごろを目標にしてたんですけどね…)
QuickJS-NG のほうはリリースが止まってしまいましたし、かと思えば今度は本家 QuickJS が立て続けに更新されていて…。(どちらも Unicode 17.0 対応はまだのようですが)
どちらを採用すればいいのか、正直なところ見通しが立たなくなってしまっている状態です。
あと本件とは直接関係ないのですが、鬼車も開発終了してしまったので、最近はなんとか Unicode 17.0 対応のメンテだけでもできないかと、ごにょごにょ試しているところです。(こちらはなんとかなりそうな気も…😏)
| Kuro | 返信 -
> そのあたり、あまり詳しくないもので、「BigInt って何?」という感じなのですが、手元の QuickJS-NG で試してみたところ、BigInt (お尻に n が付くやつ) はちゃんと使えるみたいです。
試してみていただいたようで、ありがとうございます。
ご存知かと思いますが、JavaScriptは小数の計算精度がイマイチっぽく、対処療法的に「小数を整数化してから計算。計算後に小数に戻す」みたいなことをして手元では使っていたので、「BigIntにすれば整数化が大きくできて小数計算が安定しそう…?」とか思ったのですが、残念ながらBigIntを使うだけではあまり思った改善は出きなさそうでした…😭そこで、もう自家製は諦め、math.js という外部ライブラリをv8モードで読み込ませて使う作戦に出ることにしました (Wiki掲載済み)。
Mery 電卓 - MeryWikiそのまんまmath.jsを
#includeで読み込ませて動くものかなぁ、なんて心配してましたが、すんなり使えてしまって杞憂でした。
素晴らしいライブラリのおかげで、計算精度も日常利用では困ることがない程度に。ライブラリファイル容量が600KB超な点は見ないふり見ないふり…😇> それにしても、「QuickJS 対応はいつになるの?」と思われてるかもしれませんね…😅 (ほんとは 10 月ごろを目標にしてたんですけどね…)
いえいえ、催促的な意図はもちろんありませんので。たまたま前述の電卓マクロの課題を思い出したもので、ちょっと調べていたまでです。
とはいえ、QuickJSでも上記のような外部ライブラリの
#includeでの利用がスムーズに使えるようだと嬉しいですね。> あと本件とは直接関係ないのですが、鬼車も開発終了してしまったので、最近はなんとか Unicode 17.0 対応のメンテだけでもできないかと、ごにょごにょ試しているところです。(こちらはなんとかなりそうな気も…😏)
今となっては、MeryはUnicodeにちゃんと追従している数少ない日本語エディターになっているような…w ありがたい限りです。
| yuko | 返信 -
> そのまんまmath.jsを `#include` で読み込ませて動くものかなぁ、なんて心配してましたが、すんなり使えてしまって杞憂でした。
> 素晴らしいライブラリのおかげで、計算精度も日常利用では困ることがない程度に。ライブラリファイル容量が600KB超な点は見ないふり見ないふり…😇big.js(6KB) と bignumber.js(8KB) を用途に合わせて使い分けると宜しいかと。math.jsもdecimal.jsでラップすればBigDecimalのように使えるみたいです。
https://github.com/MikeMcl| enaka | 返信 -
> ご存知かと思いますが、JavaScriptは小数の計算精度がイマイチっぽく、対処療法的に「小数を整数化してから計算。計算後に小数に戻す」みたいなことをして手元では使っていたので、「BigIntにすれば整数化が大きくできて小数計算が安定しそう…?」とか思ったのですが、残念ながらBigIntを使うだけではあまり思った改善は出きなさそうでした…😭
なるほど〜。JavaScript の小数計算の精度が微妙なのは知りませんでした。でも、業務アプリで小数の誤差が積もって「会計が 1 円合わない!」なんてのは、プログラマーあるあるですよねw
> そこで、もう自家製は諦め、math.js という外部ライブラリをv8モードで読み込ませて使う作戦に出ることにしました (Wiki掲載済み)。
おお、面白いマクロですね!日本語入りの文字列でも計算できるのはすごいです😮
> とはいえ、QuickJSでも上記のような外部ライブラリの #include での利用がスムーズに使えるようだと嬉しいですね。
ほんとそれです…。Mery + QuickJS で試しましたが、残念ながらエラーでした😅 (qjs.exeで import しても同じ結果)
> big.js(6KB) と bignumber.js(8KB) を用途に合わせて使い分けると宜しいかと。
big.js もそのままだと QuickJS ではエラーでした。どうやら QuickJS は CommonJS 形式に対応していないみたいで、ES6 形式に書き換える必要があるようです。
ES6 形式に直して
importするか、末尾のGLOBAL.Big = Big;をglobalThis.Big = Big;に書き換えて#includeすると動きました。(GLOBAL は QuickJS では使えないみたい)いやぁ、ひとりで QuickJS を検証するのもそろそろ限界かも…。
ひとまず現状できてるバージョンをリリースして、テストプレイに協力してもらえるかたちにできたらなぁ…なんて思ってみたり。(開発者本人がマクロをあんまり使いこなせてないので…🥲)
| Kuro | 返信 -
> big.js(6KB) と bignumber.js(8KB) を用途に合わせて使い分けると宜しいかと
そのあたりも考えたのですが、math.js の数式パース機能が良すぎて、容量には目を瞑る結果になってしまいました…😅
とはいえ、v8エンジンでの起動時リードタイムと相まって、起動がちょっとラグいですね。そこで、以下のような標準エンジンでのツールチップ表示 & v8マクロ起動用の軽量マクロをショートカットに登録して使うことで、処理待機中の体験を少し良くなるようにはしてみました。
#title = "Mery 電卓" Redraw = false; BeginUndoGroup(); ShowTip("計算中...", meShowTipPosCaret); editor.ExecuteMacro("MeryCalc.js"); ShowTip("", meShowTipHide);> ひとまず現状できてるバージョンをリリースして、テストプレイに協力してもらえるかたちにできたらなぁ…なんて思ってみたり。(開発者本人がマクロをあんまり使いこなせてないので…🥲)
もちろんその際にはご協力したいと思います💪
| yuko | 返信 -
「BonsTextManeger」を公開していますが、電卓機能を実装したくて調査していました。
アプリからは「Mery」を呼び出す仕組みは実装しているので、「Mery」を起動して「yuko」さんが公開している「Mery 電卓」のマクロを実行すれば電卓の機能は問題なく動作しました。電卓機能があると便利ですね。マクロの公開ありがとうございます。
「Mery」を経由しないで直接「Mery 電卓」を起動できないかと調べました。
「BonsTextManeger」では「Jscript」を以下で起動する仕組みは実装しています。
ShellExecute(Handle,'', 'WScript.exe', PWideChar(StrJScriptFileName), nil, SW_HIDE);StrJScriptFileName に「Mery 電卓.js」を設定しましたが、エラーになりました。
#title = "Mery 電卓"の「#」がエラーになります。
const inputExp = exp.replace... の「const」がエラーになります。基本的な事を理解していないと思っていますが、判る範囲でアドバイスをお願いします。
1:最初に、Delphiから「Mery」を経由しないで「Mery 電卓.js」の起動は可能なのでしょうか?
2:#language = "v8"のように、実行するスクリプトにより起動するコマンドを指定するのでしょうか?
3:#include "math_v15.0.0.js"のようにライブラリを読み込む必要がありますが、どのように指定するのでしょうか?よろしくお願いします。
| 大石剛司 | 返信 -
こんばんは~
>> yuko さん
> とはいえ、v8エンジンでの起動時リードタイムと相まって、起動がちょっとラグいですね。そこで、以下のような標準エンジンでのツールチップ表示 & v8マクロ起動用の軽量マクロをショートカットに登録して使うことで、処理待機中の体験を少し良くなるようにはしてみました。
感覚って不思議なもので、ツールチップが出るだけで逆に「計算はやっ!」って感じますね😮
そして、さっそく ShowTip を活用していただけて嬉しいです。
> もちろんその際にはご協力したいと思います💪
ありがとうございます。
次のバージョンは思い切って QuickJS-NG 対応でいこうと思います!…とはいえ、そういう時に限ってリリース直前に QuickJS-NG が更新されたりするんですよね🤣
>> 大石剛司さん
Mery 電卓、便利ですよね。私もその後愛用しています。
> StrJScriptFileName に「Mery 電卓.js」を設定しましたが、エラーになりました。
原因は大きく分けて 2 つあります。
まず、Mery のマクロは JavaScript ベースではあるのですが、独自の機能をちょっと足してあります。
たとえば
#title = "Mery 電卓"のような「#」から始まる命令は、普通の JavaScript ではなく Mery 独自の書き方です。この部分は Mery が独自に解析して動かしているので、WScript.exe ではそのまま使えません。
もうひとつ、「Mery 電卓.js」は「V8 JavaScript エンジン」で動作するように作られています。
WScript.exe が使っている「JScript エンジン」とは仕組みが違うので、そのままだと動かない箇所が出てきます。
ということで、ご質問の回答としては…
> 1:最初に、Delphiから「Mery」を経由しないで「Mery 電卓.js」の起動は可能なのでしょうか?
ちょっと手間はかかりますが、できないことはないかと思います😅
やることとしては、
- Mery 独自の書き方を全部取り除く
- WScript.exe ではなく V8 JavaScript エンジンで実行する
この 2 つです。
V8 JavaScript エンジンは、Delphi の TEdgeBrowser (WebView2) を使えば実行できます。(Mery もこの WebView2 の V8 エンジンを使っています)
あまり良いサンプルは見つからなかったのですが…
【参考】TEdgeBrowserを使用してスクリプトを実行する方法
https://blogs.embarcadero.com/ja/execute-scripts-and-view-source-with-tedgebrowser-ja/↑公式ではいろいろ書かれていますが、実際のところ WebView2 SDK やランタイムを別途インストールする必要はなく、WebView2Loader.dll を exe と同じフォルダに置くだけで動くと思います。
> 2:#language = "v8"のように、実行するスクリプトにより起動するコマンドを指定するのでしょうか?
#language = "v8"も Mery 独自の書き方で、JavaScript 標準の構文ではありません。この指定があると、Mery がマクロ実行時に JScript ではなく TEdgeBrowser の V8 エンジンを使うように切り替えています。
> 3:#include "math_v15.0.0.js"のようにライブラリを読み込む必要がありますが、どのように指定するのでしょうか?
これも Mery 独自の仕組みです。
Mery は
#includeがあると、そのファイルを読み込んでマクロの先頭にくっつけて実行します。いわばシンプルな「貼り付け型インクルード」です。ということでまとめると、
- WScript.exe → TEdgeBrowser に置き換える
- Mery 独自の記法を削除する
- math_v15.0.0.js の内容をコードの先頭に貼り付ける
…といった流れになります。
「Mery 電卓.js」の
document.selectionなども Mery 独自のオブジェクトなので、この辺りを整理するのは少し手間がかかるかもしれません。もしシンプルに「計算だけ」を動かしたい場合は、主要なロジック部分だけを切り出して、純粋な JavaScript としてまとめたほうがスッキリすると思います。
| Kuro | 返信 -
もうCalc (C言語風計算コマンド)みたいなのをCライブラリとしてリンクする方が早い気が。
https://github.com/lcn2/calc自分は単にCalcをMeryの外部コマンドに登録して使ってます。Windowsではファイル名がcalc.exeで丸被りなので要変更。
| enaka | 返信 -
確かに!わざわざ JavaScript を使わなくても、Delphi から直接計算ライブラリを使ったほうがずっと簡単ですね😅
QuickJS スレッドということもあって、「どうにか JavaScript でやらなきゃ…」と、つい一直線に突き進んでしまいましたー
| Kuro | 返信 -
>> Kuroさん、大石剛司さん
おおっ、Mery 電卓をお試しいただいてありがとうございます。ちょっとしたテキスト計算ができると便利ですよね。
Mery 電卓 ですが、
$100 * 12のようなドル付き数字の計算をするとエラーになってしまっていたので、整形の処理を少し調整してアップデートしました。よろしければどうぞ!また、enakaさんが「そもそも外部コマンドを使えばいいのでは?」という話をしてくださったことで「あ、たしかに…」と灯台下暗しな気づきがあり、もっと軽快に動作させられるような方法はないかと調べていました。そうしたところ、 BusyBox for Windows という、LinuxのメジャーなコマンドをWindowsでも簡単に扱える超軽量なポータブル実行ファイルに行き着き、それを使って
bcコマンドを使う方法に至りました。そして、派生版となる Mery 電卓 (bc コマンド使用版) を作成してみました。
以前Kuroさんにこしらえていただいた
shell.Exec()を使い、BusyBox内のbcコマンドを実行……これで、無事に動きました!使用感や計算精度はそのままに、マクロ本体では標準のJScriptエンジンを使うようにしたことで、本家「Mery 電卓」よりも起動速度がだいぶ改善されました。bcコマンドを使うようにしたことで数学関数のバリエーションは限定的になってしまいましたが、そもそも「日常のテキストからラフに計算をしたい」というコンセプトから生まれたマクロなので、このくらいが良いのかもしれません😊しかし、BusyBox for Windows、可能性の塊ですね。
shell.Exec()との組み合わせで、かなり幅広いことがこれ一本でできそうです。 BusyBox - The Swiss Army Knife of Embedded Linux > COMMANDS に記載のコマンドが使えるとのことで、grep やら awk やら圧縮・解凍やらと、面白いですね。| yuko | 返信 -
>> Kuroさん
> 次のバージョンは思い切って QuickJS-NG 対応でいこうと思います!
おおっ、いよいよ。気持ちを強く持って公開してくださいw
ちなみに、もし既に考慮済みだったらすみませんが、
#languageのデフォルト値を設定する隠しオプションを用意してはいかがでしょうか?実際に試してみるときのことを考えたときに以下のような状況があるかなと思いまして。
- 使っているマクロがたくさんあるので、それごとにQuickJS使用の宣言を入れるのが大変
- QuickJSは、いずれJScriptが使えなくなったら…というのを見据えた対応だと思うので、デフォルトで使っていけるかという観点で試してみたい
| yuko | 返信 -
>> yuko さん
> そして、派生版となる Mery 電卓 (bc コマンド使用版) を作成してみました。
早速試させていただきました!起動が速くて、とても快適ですね。さらに、QuickJS でもそのまま動作しました。
BusyBox は以前、ルーターを改造するときに Linux で使ったことがあったのですが、Windows 上で、しかもこんなに軽量に使えるとは知りませんでした。
COMMANDS を眺めていると、夢がどんどん膨らみます😍 まるで小さな Linux のようで、何でもできそうな勢いですね。httpd まで入ってるとは…。
おっしゃるとおり、
shell.Exec()と組み合わせるとさらに可能性が広がりそうです。めちゃくちゃ軽量なので導入も簡単ですし、これは面白いものを教えていただきました。私も何かに活用してみたいです!
> おおっ、いよいよ。気持ちを強く持って公開してくださいw
目標をセンターに入れてスイッチ。目標をセンターに入れてスイッチ😱
> ちなみに、もし既に考慮済みだったらすみませんが、 #language のデフォルト値を設定する隠しオプションを用意してはいかがでしょうか?
なるほど、それは確かにアリですね。
それなら、[マクロ] の [記録] で記録したメモリ上の一時マクロの実行も、そのデフォルト値を使うようにすると便利かもしれません。
ただ少し問題なのは、
#languageを省略したときのデフォルト値にしてしまうと、たとえばMery.iniで…[Macros] DefaultLang=quickjsのような指定にした場合、VBScript や Python Script を使うときに
#languageを省略できなくなってしまいますね。なので、設定としては「デフォルトの JavaScript エンジンとして QuickJS を使うかどうか」のフラグにするほうが自然かもしれません。
[Macros] UseQuickJS=1こうしておけば、.vbs や .pys のときは従来どおり動作し、.js の場合に
#languageを省略すると JScript9 ではなく QuickJS を使う、という挙動にできます。さらに将来的に JScript が使えなくなった場合でも、
UseQuickJS=1を初期値にしてリリースすればいいだけなので、対応もシンプルになりそうですね。| Kuro | 返信 -
> > そして、派生版となる Mery 電卓 (bc コマンド使用版) を作成してみました。
bcコマンドの元であるRPN計算するdcコマンドはUNIX最古のコマンドだとか。アセンブラより先に作ったとUNIXとC言語の父ケン・トンプソン先生が言っていました。
> COMMANDS を眺めていると、夢がどんどん膨らみます😍 まるで小さな Linux のようで、何でもできそうな勢いですね。httpd まで入ってるとは…。
無線ホームルータなどの簡単なWEBインターフェイスは、Apacheなどを入れる余裕がない場合はそのhttpdで動いています。
今でこそ組み込み機器がメインですが、FDD/HDDからしか起動できなかった頃、1FD Linuxインストーラとか1FD LinuxルータとかBusyBOXは必須でした。> > おおっ、いよいよ。気持ちを強く持って公開してくださいw
>
> 目標をセンターに入れてスイッチ。目標をセンターに入れてスイッチ😱逃げちゃだめだ、逃げちゃだめだ(お約束)
| enaka | 返信 -
BusyBox、私は言葉だけは聞いたことがある程度だったんですが、へぇ、そういう色んな製品の中で動いていたんですね~😲 技術者の方々の努力が垣間見えますね。
>> Kuroさん
> [Macros]
> UseQuickJS=1おー、たしかに
#languageを直接変えるような動きにしてしまうとVBSなどの言語の判別が効かなくなってしまいそうので、こっちの方がよさそうですね。さすが目の付けどころがシャープですね。ところで Mery 電卓 (bc コマンド使用版) - MeryWiki ですが、「5 - 3.0」のような「小数以下が『.0』になる計算」で「.」だけが出力に残ってしまう不具合があったので微修正しました。
作りたてでちまちま修正を入れてしまって心苦しいですが、ひとまずお知らせまで。
| yuko | 返信 -
外部Mathライブラリに依存せず、POSIX準拠、GNU拡張(Piなど)対応、BSDライセンス、で高速なbcコマンドを見つけました。
Windowsバイナリも配布されています。https://github.com/gavinhoward/bc
bcスクリプト拡張も実装されていて、FreeBSDではOpenBSD由来のbcからgavin-bcに置き換えられたようです。
MSYS2環境で-O3でビルドしてbcスクリプトで繰り返し計算すると、確かにGNU bcより速いです。history有効だとビルドエラーになりました。$ wget https://github.com/gavinhoward/bc/releases/download/7.0.3/bc-7.0.3.tar.gz
$ tar zxvf bc-7.0.3.tar.gz
$ cd bc-7.0.3/
$ configure --disable-history
$ make
$ ls -l bin/
-rwxr-xr-x 1 enaka None 174592 2025-10-26 20:38 bc.exe
lrwxrwxrwx 1 enaka None 6 2025-10-26 20:38 dc.exe -> bc.exe
$ ldd bin/bc.exe
ntdll.dll => /win/SYSTEM32/ntdll.dll (0x7ffd5ef70000)
KERNEL32.DLL => /win/System32/KERNEL32.DLL (0x7ffd5d030000)
KERNELBASE.dll => /win/System32/KERNELBASE.dll (0x7ffd5cc40000)
msys-2.0.dll => /usr/bin/msys-2.0.dll (0x180040000)| enaka | 返信 -
> history有効だとビルドエラーになりました。
ヘッダを一つ追加して解決。多分この設定が一番速いと思います。
$ CC=c99 ./configure --opt=3 --disable-nls --prefix=/usr
$ echo "#include <sys/socket.h>" >> ./include/history.h
$ make
$ make install
$ gencat bc.cat locales/ja_JP.UTF-8.msg
$ cp bc.cat /usr/share/locale/ja/| enaka | 返信 -
> 派生版となる Mery 電卓 (bc コマンド使用版) を作成してみました。
マクロの公開ありがとうございます。
「V8」で記述したスクリプトを Delphi から起動しようとして「TEdgeBrowser」で試みましたが、挫折しました。
次に「BusyBox.exe」を使用して、「Jscript」での動作に変更して、試行錯誤の結果、ようやく動作させるところまで到達できました。ただ「BusyBox.exe」を起動すると一瞬画面が見えて直ぐに閉じるという状況になっていて、今のところは、この解決方法が見つけられていません。
Mery 電卓 (bc コマンド使用版) で理解できていない箇所があるので、判る範囲で教えて下さい。
1:var exp_replaced = replaceExpression(exp)
2: .replace(/([^;]*%[^;]*)/g, "scale=0; $1; scale=10; "); // 剰余計算を整数にする
3: const exec = shell.Exec(busyboxPath + " bc -l", "scale=10; " + exp_replaced);(2)の scale=0 と scale=10 の使い方が判りません
(3)の "scale=10; " を削除しても同じように動作しますが、必要でしょうか?ちなみに、計算以外は Delphi 側で作成し、計算は Script で実行しています。
よろしくお願いします。
| 大石剛司 | 返信 -
> Mery 電卓 (bc コマンド使用版) で理解できていない箇所があるので、判る範囲で教えて下さい。
> (2)の scale=0 と scale=10 の使い方が判りません
> (3)の "scale=10; " を削除しても同じように動作しますが、必要でしょうか?話が戻ってる(笑)
bcのscaleを使って計算精度を稼いでいるのです。| enaka | 返信 -
> > Mery 電卓 (bc コマンド使用版) で理解できていない箇所があるので、判る範囲で教えて下さい。
> > (2)の scale=0 と scale=10 の使い方が判りません
> > (3)の "scale=10; " を削除しても同じように動作しますが、必要でしょうか?
>
> 話が戻ってる(笑)
> bcのscaleを使って計算精度を稼いでいるのです。
>
> https://qiita.com/h-pod/items/d8b98b00538d292e0c81違った。-lオプションはscale=20相当なので、むしろ精度を落として速度を稼いでいるのか。
| enaka | 返信 -
> (2)の scale=0 と scale=10 の使い方が判りません
> (3)の "scale=10; " を削除しても同じように動作しますが、必要でしょうか?これは、enakaさんが触れてくださったように、計算精度を調整する指定です。
まず
bcコマンドの仕様の認識合わせですが、以下のように、scale=nの指定を変えますと、小数点以下の桁数をどこまで計算するかが変化します。ただし-lオプションを用いていることでデフォルトがscale=20となっているため、以下の (3) (4) からは同じ結果が得られています。# (1) ❯ echo 'scale=0; 10 / 3' | .\busybox64u.exe bc -l 3 # (2) ❯ echo 'scale=10; 10 / 3' | .\busybox64u.exe bc -l 3.3333333333 # (3) ❯ echo 'scale=20; 10 / 3' | .\busybox64u.exe bc -l 3.33333333333333333333 # (4) ❯ echo '10 / 3' | .\busybox64u.exe bc -l 3.33333333333333333333そして、ご質問の
> (3)の "scale=10; " を削除しても同じように動作しますが、必要でしょうか?
で
scale=10を使っているのは、「日常の計算において小数点以下20桁もの精度は不要」「循環小数の結果を20桁も出したくない」「少しでも計算が早い方がいい」といったあたりの理由から適当に「10」としています。そして
> (2)の scale=0 と scale=10 の使い方が判りません
については、複数の数式を渡した場合に、精度を一時的に変更することを考慮しているためですね。
例えば、「Mery 電卓 (bc コマンド使用版)」では、以下のような複数数式の入力にも対応しています。
ケース 1、下記のような複数行を選択して実行する場合:
10 / 3 5 % 3 10 / 3ケース 2、下記のように「;」区切りで複数個になっている数式の行で実行する場合:
10 / 3; 5 % 3; 10 / 3これらで実行する場合、現行仕様だと以下の通りになります。
10 / 3; 5 % 3; 10 / 3 = 3.3333333333 ; 2 ; 3.3333333333これは、マクロ内部では剰余計算「%」が含まれる数式の箇所のみ
scale=0とscale=10で挟み込む置換をすることによって、以下のようなbcコマンド実行と同じ内容になるように整形することで実現しています。echo 'scale=10; 10 / 3; scale=0; 5 % 3; scale=10; 10 / 3' | .\busybox64u.exe bc -lもしマクロで
scale=0とscale=10で挟み込む置換をせず、scale=0だけを剰余式の箇所で差し込むと、数式の順番によっては以下のように精度のバラつきが出てきます。10 / 3; 5 % 3; 10 / 3 = 3.3333333333 ; 2 ; 3……というような理由から、マクロ内では文字列をがんばってこねくり回している感じです。うまく伝わればいいのですが…😅
| yuko | 返信 -
enaka さん
説明のリンク先を教えていただきありがとうございます。
自分でも探しましたが見つからなかったので助かりました。
内容を読んで納得しました。yuko さん
単一の計算でしか検証していなかったので違いは出ませんでしたので、私が間違って理解していました。
詳しい説明ありがとうございます。
先頭でデフォルトの設定を記述して、剰余の前に精度を落として、剰余の後で精度を戻すという理解で合っていますよね。「BonsTextManager」に電卓の機能を追加しましたが、もう少し検証してから公開します。
複雑な計算は省きたいので「-l」のオプションは削除しました。
これにより変数の先頭の $ を省く事が可能になり、$ 無しでの変数の使用が可能になりました。Kuro さん
相変わらず、一瞬画面がブリンクする不具合は解決できていません。
以下の内容で起動していますが、「Mery」との違いがあれば教えて下さい。procedure TFormMain.MenuCalBusyBoxClick(Sender: TObject); var sStr11: String; sStr12: String; sStr13: String; bgin // 実行 sStr11 := 'WScript.exe'; // Exe sStr12 := '"' + System.IOUtils.TPath.GetDirectoryName(ParamStr(0)) + '\' + 'Cal.js' + '"'; // File sStr13 := ''; ExecuteRerated(sStr11, sStr12, sStr13); end; function TFormMain.ExecuteRerated(AFileName: String; AOption: String; AWorkDirectory: String): Boolean; var iErr1: Integer; bRet1: Boolean; begin // 起動 iErr1 := ShellExecute(Handle, 'open', PWideChar(AFileName), // 対象ファイル名 "D:\a.txt" // "C:\tool\annsFMimage.exe" PWideChar(AOption), // オプション設定 /J=300 // hwic=1234 "C:\tmp\123.jpg" PWideChar(AWorkDirectory), // 作業フォルダ名 SW_SHOWDEFAULT); // 失敗 if iErr1 <= 32 then begin Result := FALSE; end // 成功 else begin Result := TRUE; end; end; ===================================================== Cal.js ===================================================== var calExePath = "D:\\DLPH_SRC\\#PERSONAL\\XE12-32-BonsTextManager\\Win32\\Release\\busybox.exe" var calFilePath = "D:\\DLPH_SRC\\#PERSONAL\\XE12-32-BonsTextManager\\Win32\\Release\\CalFile.txt" var shell = new ActiveXObject('Wscript.Shell'); var exec = shell.Exec(calExePath + " bc -q " + calFilePath); =====================================================よろしくお願いします。
| 大石剛司 | 返信 -
>> 大石剛司さん
> 相変わらず、一瞬画面がブリンクする不具合は解決できていません。
> 以下の内容で起動していますが、「Mery」との違いがあれば教えて下さい。これは不具合というより、WScript の仕様だと思います。
WScript.Shell の
Execメソッドには、コマンドプロンプトなどを非表示で実行する機能がなかったと思います。Mery 電卓で使われている
shell.Execは、名前こそ同じですが WScript のものではなく、Mery 側で独自に用意しているもので、ウィンドウを非表示で実行できるようになっています。WScript で同じことをやる場合は、
shell.Execではなくshell.Runを使い、第 2 引数に 0 を渡すとウィンドウを非表示にできたはずです。でも、特に WScript (Cal.js) を経由する理由がなければ、Delphi から直接
ShellExecuteでSW_HIDEオプションを指定してbusybox.exeを呼び出すのが、いちばんシンプルだと思います。| Kuro | 返信 -
情報ありがとうございます。
>Mery 電卓で使われている shell.Exec は、名前こそ同じですが WScript のものではなく、Mery 側で独自に用意しているもので、ウィンドウを非表示で実行できるようになっています。
独自に実装しているとの事で納得できました。
実は「busybox.exe bc」で起動した後に結果を取得するには、標準出力を使用する必要があります。
これが実現できるのが、Script の「shell.Exec(calExePath + " bc -q " + calFilePath);」でした。アドバイスを元に、頭をクリアにして、あれこれと試してみました。
バッチファイルの中で、ファイル名の指定がフルパスでなくファイル名の場合は、「busybox.exe」でも リダイレクトが使用できました。最終的に、実行するフォルダを「busybox.exe」のあるフォルダに変更して、バッチファイルを起動する事で目的の動作になりました。これで完成かなと思います。
アドバイス、ありがとうございました。
const CAL_EXE = 'busybox.exe'; CAL_BAT = 'Cal.bat'; CAL_IN_TXT = 'CalIn.txt'; CAL_OUT_TXT = 'CalOut.txt'; procedure TFormMain.MenuCalBusyBoxClick(Sender: TObject); var StrList4: TStringList; sStr11: String; sStr12: String; sStr13: String; sStr24: String; bgin // バッチファイルを作成 // busybox.exe bc -q calin.txt > calout.txt // カレントディレクトリを変更するのでファイル名にパスは不要 // 確保 StrList4 := TStringList.Create; // 保存 StrList4.Add(CAL_EXE + ' bc -q ' + CAL_IN_TXT + ' > ' + CAL_OUT_TXT); StrList4.WriteBOM := FALSE; StrList4.SaveToFile(sStr24, TEncoding.UTF8); sleep(100); // 破棄 StrList4.Free; // 設定 sStr24 := System.IOUtils.TPath.GetDirectoryName(ParamStr(0)) + '\' + CAL_BAT; // 実行 sStr11 := '"' + sStr24 + '"' ; // Exe sStr12 := ''; // File sStr13 := '"' + System.IOUtils.TPath.GetDirectoryName(ParamStr(0)) + '"'; // Directory ExecuteReratedHide(sStr11, sStr12, sStr13); end; function TFormMain.ExecuteRerated(AFileName: String; AOption: String; AWorkDirectory: String): Boolean; var iErr1: Integer; bRet1: Boolean; begin // 起動 iErr1 := ShellExecute(Handle, 'open', PWideChar(AFileName), // 対象ファイル名 PWideChar(AOption), // オプション設定 PWideChar(AWorkDirectory), // 作業フォルダ名 SW_HIDE); // 表示させない // 失敗 if iErr1 <= 32 then begin Result := FALSE; end // 成功 else begin Result := TRUE; end; end;| 大石剛司 | 返信 -
> 実は「busybox.exe bc」で起動した後に結果を取得するには、標準出力を使用する必要があります。
なるほど、そうでしたか。その場合は
shell.Runでは対応できませんね。ともあれ、目的の動作になったとのことで良かったです。
> 最終的に、実行するフォルダを「busybox.exe」のあるフォルダに変更して、バッチファイルを起動する事で目的の動作になりました。これで完成かなと思います。
バッチファイルを生成して実行とは、なかなかワイルドな解決法ですね…😅
ちなみに、Mery のウィンドウ非表示
shell.Execで使っているのは、Mr.XRAY さんのplCommandRedirect.pasです。【参考】[ 552_パイプを使用したコマンドラインのリダイレクト ] - Mr.XRAY
https://mrxray.on.coocan.jp/Delphi/plSamples/552_PipeRedirect.htmページの上のほうにある
552_PipeRedirect.zipからダウンロードできます。Delphi の
ShellExecuteの代わりにplCommandRedirect.pasを使えば、標準出力を簡単に拾えるうえにウィンドウも非表示にできるので、今後ほかのコマンドを扱うときにもけっこう便利ですよ。| Kuro | 返信 -
> 次のバージョンは思い切って QuickJS-NG 対応でいこうと思います!…とはいえ、そういう時に限ってリリース直前に QuickJS-NG が更新されたりするんですよね🤣
はい、見事にフラグ回収しました。
quickjs-ng v0.11.0、来てました。
【参考】GitHub - quickjs-ng/quickjs: QuickJS, the Next Generation: a mighty JavaScript engine
https://github.com/quickjs-ng/quickjsしかも、鬼のようなアップデート量。(∩゚д゚)アーアーキコエナーイ
正直、「もう見なかったことにして、このままリリースしちゃおうか…」とも思いましたが、本家 QuickJS の CVE 修正も取り込まれているとのことで、さすがにスルーできず。
バグフィックスはありがたい反面、仕様変更も大量で、しかもよりによってリリース直前…。また検証からやり直しです😭
先日の未実装やらかしに追い打ちをかけるかたちで、まさに泣きっ面にアンメルツ状態です。
| Kuro | 返信 -
> バグフィックスはありがたい反面、仕様変更も大量で、しかもよりによってリリース直前…。また検証からやり直しです😭
自動テストの仕組みがないと永久に追いつけない気がします(笑)
コミットログを見た感じ、マージ済みのパッチでステータスが未検証のものが結構残っているのと、これまでの半年弱間隔での大変更リリースとその数週間くらい後の小変更リリースの実績から、今回は前者的なベータ版色の強いリリースな気がします。本家とNg両対応のプロジェクトとかどういう仕組みなんでしょうね。
https://github.com/HiRoFa/quickjs_es_runtime| enaka | 返信 -
> 先日の未実装やらかしに追い打ちをかけるかたちで、まさに泣きっ面にアンメルツ状態です。
染みるわ、クサいわ、で非常にアレな感じで……w
QuickJS-NGの更新量は相変わらずすごいですねぇ。enakaさんおっしゃるように自動テストでも用意しないと厳しそうですね…😥
| yuko | 返信 -
試しにMSYS2のgnuplotを外部コマンドで呼び出したらグラフ電卓が出来ました。
$ pacman -S mingw-w64-ucrt-x86_64-gnuplot
:
$ gnuplot -V
gnuplot 6.0 patchlevel 3
$ echo "splot x**2+y**2" | gnuplot -p -dgnuplot公式サイトに普通のWindowsインストーラ版も日本語マニュアルもあります。
来年でgnuplotは40周年。Xlibの古臭いUIがQtで刷新されたのが最近と思っていたが20年前。時間が、時間が経つのが速い。
NumPy/SciPy/SymPyによる数値解析が広まっていますが、数値解析ソフトは研究者が自分用に作っているからか、OctaveやScilabやRなどの老舗でも現在も活発に開発され続けているものが多いですね。
| enaka | 返信 -
>> enaka さん
> 自動テストの仕組みがないと永久に追いつけない気がします(笑)
自動テストと言われても、そもそも「何をテストすればいいのか」がわからないニワカプログラマーなもので😱
もっぱらメッセージボックス「unco」でデバッグしてますね (小学生未満)
> コミットログを見た感じ、マージ済みのパッチでステータスが未検証のものが結構残っているのと、これまでの半年弱間隔での大変更リリースとその数週間くらい後の小変更リリースの実績から、今回は前者的なベータ版色の強いリリースな気がします。
v0.10.0 のときもそんな感じでしたね。すぐに v0.10.1 が出て、「ウワーン😭」ってなった記憶があります。
> 本家とNg両対応のプロジェクトとかどういう仕組みなんでしょうね。
> https://github.com/HiRoFa/quickjs_es_runtimeソースコードを拝見した感じだと、QuickJS のアップデートをかなりこまめに追いかけているようです。
C++ アプリならヘッダをそのまま使えるので対応も早いと思いますが、この方は Rust ですし、Mery は Delphi なので、一度「翻訳」する必要があるんですよね。
その部分だけでも、もはや 1 つのプロジェクトとして成立しそうな作業量です…。
>> yuko さん
> QuickJS-NGの更新量は相変わらずすごいですねぇ。enakaさんおっしゃるように自動テストでも用意しないと厳しそうですね…😥
ほんとですよね。半年ぐらい音沙汰なかったと思ったら、ここにきてブァーっと来ましたね。
自動テスト……という名の、ベータ版ユーザー様😏
> 染みるわ、クサいわ、で非常にアレな感じで……w
v0.11.0 のビルドまではなんとか行けたのですが、実行してみたら案の定エラー祭りで動かず。「仕様変更かーーー!」って叫びました😂
「ヨコヨコ」の意味はいまだによくわかっていませんが、ほんとそんな感じのダメージで、この連休は現実逃避して Web プレビュープラグインの Edge (WebView2) 版を作ってました。
はぁ……なんだか v0.11.1 もすぐ来そうで怖いです。
| Kuro | 返信 -
DelphiのUnitテストというとDUnitしかわからない。
> 自動テストと言われても、そもそも「何をテストすればいいのか」がわからないニワカプログラマーなもので😱
Delphi Unit Test Framework
https://github.com/VSoftTechnologies/DUnitX/DUnitXの紹介
https://gesource.jp/programming/delphi/xe8/dunitx/> 「ヨコヨコ」の意味はいまだによくわかっていませんが、ほんとそんな感じのダメージで、この連休は現実逃避して Web プレビュープラグインの Edge (WebView2) 版を作ってました。
日本家庭薬協会 家庭薬ロングセラー物語 アンメルツ
https://www.hmaj.com/kateiyaku/anmerutsu/| enaka | 返信 -
>plCommandRedirect.pas
教えていただいた内容をダウンロードしました。付属しているサンプルが動作したので、「BonsTextManager」に組み込んでみました。
試しに添付している「Unit1」を「show」で表示させました。「cmd.exe /k」で「dir」を実行してみましたが出力には何も表示されませんでした。という事で、別の機会に使ってみます。
一方「busybox.exe」をバッチファイルで起動する件ですが、「busybox.exe」がエラーが発生した時の処理が出来なくて、こちらも挫折しました。
最終的に WEB にあった「式の評価(数式の計算)」を組み込みました。
http://hiderin.air-nifty.com/delphi/2008/04/post_1432.html四則演算のみの機能ですが私の目的にはピッタリでした。処理も早いのでストレスなしです。
もう少し様子を見てから公開する予定です。
よろしくお願いします。
| 大石剛司 | 返信 -
Kuroさん
ver 3.8.0、まずは、リリースお疲れさまでした!
早速、ワクワクとしながら
UseQuickJS=1をiniに仕込んでみました。ひとまず私の環境では以下のように、
Tagの呼び出し方をMacrosフォルダー内を一括で置換することで、概ね動くようになりました。- 置換前:
([ !-/:-@[-{-~])[tT]ag(([^)]+))` - 置換後:
$1tag[$2]
あとは、言語仕様が厳密化されたのだと思いますが、以下のような状況も見られ、適宜修正しました。
- var 宣言が無いと例外が出る
selection.UnIndent()(※「I」が大文字) はJScriptのときはなぜか通っていたが、例外が出るようになった
今のところ、たんまり存在するマクロも
Tagの一括置換でほとんどの修正が終えてしまったので、互換性の高さに驚きです。どうなるかなーと思っていた、いくつかnew ActiveXObject()を使っているマクロもあったのですが、問題なく動いています🥳各マクロの初動がちょっぴり速くなったような気がしているのですが、心なしか、Mery本体の起動速度もコンマ数秒ほど速くなったような気がしています (さすがに気のせい?)。
| yuko | 返信 - 置換前:
-
ありゃ、一括置換条件が一部Markdown書式と競合してしまったので再掲…
- 置換前: ([ !-/:-@[-`{-~])[tT]ag\(([^\)]+)\) - 置換後: $1tag[$2]| yuko | 返信 -
早速お試しいただき、ありがとうございます!
> 早速、ワクワクとしながら UseQuickJS=1 をiniに仕込んでみました。
それ、ちょっと早すぎますってば😅
> ひとまず私の環境では以下のように、 Tag の呼び出し方をMacrosフォルダー内を一括で置換することで、概ね動くようになりました。
なるほどー、それですね。私も検証のときに引っかかっていたのですが、yuko さんは V8 エンジンで Tag プロパティを使っていたので、たぶんピンと来るかなーと思っていました。
> var 宣言が無いと例外が出る
これはそうなりますね。いきなり変数が出てきたらダメみたいです。QuickJS の仕様みたいです。
> selection.UnIndent() (※「I」が大文字) はJScriptのときはなぜか通っていたが、例外が出るようになった
QuickJS ではメソッド名の大文字/小文字が区別される仕様になってますね。
一応、既存のマクロとの互換性をできるだけ維持するため、1 文字目だけは大文字/小文字どちらでも通るようにしています。(これを除去すると、もう少し速くなるかも)
> 今のところ、たんまり存在するマクロも Tag の一括置換でほとんどの修正が終えてしまったので、互換性の高さに驚きです。
Tag は、JScript のメソッドのような書き方に代入できる仕様が謎だっただけで、正しい仕様になった、と言ったほうがよさそうですね。
> どうなるかなーと思っていた、いくつか new ActiveXObject() を使っているマクロもあったのですが、問題なく動いています🥳
ActiveXObject は鬼門でしたねぇ😁
どこまで JScript の ActiveXObject を再現できているかはまだ未知数なので、うまく動かないものもあるかもしれません。動作検証にご協力いただけると助かります。
> 各マクロの初動がちょっぴり速くなったような気がしているのですが、心なしか、Mery本体の起動速度もコンマ数秒ほど速くなったような気がしています (さすがに気のせい?)。
QuickJS の初動は結構速いですよね。実行速度としては、JScript9 よりは遅く、JScript9Legacy よりは速い、といった感じだと思います。
Mery の起動速度は、ファイル読み込みの処理をちょっと改善して若干速くなっているので、ワークスペース機能を使っている場合は、起動速度も少し速くなっているかもしれません。
あとは、QuickJS が近日中に更新されないことを祈るのみです。(と、フラグをオッ立てておきますw)
| Kuro | 返信 -
> > 早速、ワクワクとしながら UseQuickJS=1 をiniに仕込んでみました。
>
> それ、ちょっと早すぎますってば😅自分程度の使い道では、全く問題なかったです。
> > 各マクロの初動がちょっぴり速くなったような気がしているのですが、心なしか、Mery本体の起動速度もコンマ数秒ほど速くなったような気がしています (さすがに気のせい?)。
>
> QuickJS の初動は結構速いですよね。実行速度としては、JScript9 よりは遅く、JScript9Legacy よりは速い、といった感じだと思います。Ryzen7 3700X だと違いが分かりませんが、Core i5-8250U だと初回は半呼吸速い気がします。
> あとは、QuickJS が近日中に更新されないことを祈るのみです。(と、フラグをオッ立てておきますw)
身構えている時には、死神は来ないものだ(お約束)
| enaka | 返信 -
早速お試しいただき、ありがとうございます。
> 自分程度の使い道では、全く問題なかったです。
動作検証にご協力いただき、ありがとうございます。
逆に何も起きなさすぎて少し怖いくらいですが、ひとまず問題なさそうとのことで安心しました。
> Ryzen7 3700X だと違いが分かりませんが、Core i5-8250U だと初回は半呼吸速い気がします。
初回は DLL の読み込みがあるので、差が出るとしたら HDD アクセス速度か、ウイルス対策ソフトによる qjs.dll のスキャンが走るか、そのあたりの違いだと思います。
でも、V8 エンジンと比べると桁違いに速いですね。
> 身構えている時には、死神は来ないものだ(お約束)
そこ、とおってなくてすみません😅
ガンダムは見ていなかったので、子どものころ友達とプラモデルを買いに行ったときも、友達はガンダムをゲット。私は在庫がなくて、仕方なくキュベレイというよく知らないキャラを買った、という悲しい思い出があります。
そういえば、ミニ四駆を買いに行った時も友達がアバンテをゲットして、私は在庫がなくてバーニングサンというよくわからない車種を買ったこともセットで思い出してしまいました。やだー。
よしよし、まだ QuickJS は更新されていないみたいですね。
v0.10.0 → v0.10.1 が約 2 週間だったので、今回も同じペースだったらどうしようと思っていましたが、もう 3 週間を超えたので、しばらく…2 カ月くらい?は安心できそうですね。
| Kuro | 返信 -
Ver 3.8.0 のリリースお疲れ様です。
自作のマクロはもともと Strict mode で動くかチェックしてたので全部問題なく動いてます。
MeryWiki に投稿したUnicode正規化マクロをさっそく QuickJS を使用するように更新してみました。
それにしても速いですね!
上記マクロを 10000 行の文書で 10000 個選択して実行したところ、Core i5-6200U では V8 だと 20 秒かかっていたのが QuickJS だと 6 秒くらいに、Core i5-12500 では V8 だと 6 秒かかっていたのが QuickJS だと 1 秒ちょっとになりました。[オプションを指定して実行] でも QuickJS が使えるんですね。JScript よりできることが増えてるので一行マクロでも活躍しそうです。ちなみに上述のテストで使用したテキストは下記のような感じで [オプションを指定して実行] で作成しました。
qjs:document.selection.Text='\u2460\u304B\u3099\n'.repeat(10000);| ucky | 返信 -
早速お試しいただき、ありがとうございます。
> 自作のマクロはもともと Strict mode で動くかチェックしてたので全部問題なく動いてます。
その互換性、すごいですね…。まさかそこまで問題なく動くとは思っていませんでした。
> MeryWiki に投稿したUnicode正規化マクロをさっそく QuickJS を使用するように更新してみました。
更新ありがとうございます。おぉ、爆速になってますね!
Unicode 正規化マクロは検証段階で教えていただいて、開発中も動作確認に使わせてもらって本当に助かりました。
V8 と比べると、やっぱり QuickJS は初速が段違いに速いですよね。よほど特殊なケースじゃない限り、もう V8 の出番は少なくなるかもしれませんね。
とはいえ、
fetchやsetTimeoutのように QuickJS では使えない部分もあるので、そのあたりはうまく使い分けになりそうですが…。> [オプションを指定して実行] でも QuickJS が使えるんですね。JScript よりできることが増えてるので一行マクロでも活躍しそうです。
おぉ…。[オプションを指定して実行] を使っている方はほとんどいないと思っていたので、QuickJS 対応については特に触れていなかったのですが、
qjs:に気づくとはさすがです。それに合わせて、
js:はJScript9Legacy、js9:はJScript9に割り当てています。ちなみに余談ですが、QuickJS については今のところ不具合は確認できていません。…が、例によって、リリースした直後にバグを見つけてしまう現象が今回も発動してしまいまして。
次のバージョンで修正予定です。(UTF-8 (BOM 付き) のファイルがバイナリ モードで開けない)
| Kuro | 返信 -
いま気づいたのですが、
window.ShowTip()がQuickJSだと使えないかもしれません… 🤔実行時に
TypeError: not a functionエラーが出てしまうようです。| yuko | 返信 -
おおー、これは実装漏れでした😅
QuickJS と JScript/V8 系はまったく別ロジックで二重管理になっているので、どこかに抜けがあるだろうな…とは思っていたのですが、ご報告いただき本当に助かります。
次のバージョンで対応しておきますね!
| Kuro | 返信