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: 84
main.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.00ms
Mery では、
#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.js
import * 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.00ms
32 ビット版より少し速いですね。あと、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 MB
JerryScript は、確かにメモリ使用量が少ないですね。さすが小型デバイス向け。実行ファイルのサイズが小さいことも影響しているのかもしれませんが。
ただ、実行速度は 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 | 返信