昔のHDDからデータをあさっていたときに過去の遺物を見つけたので次に使うかもしれないときのためにメモ。 Delphiで書いたSpiderMonkeyのサンプルなんてほかに誰が必要としているんだか。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, jsapi;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
global_class: JSClass = (
name: 'global';
flags: 0;
addProperty: JS_PropertyStub;
delProperty: JS_PropertyStub;
getProperty: JS_PropertyStub;
setProperty: JS_PropertyStub;
enumerate: JS_EnumerateStub;
resolve: JS_ResolveStub;
convert: JS_ConvertStub;
finalize: JS_FinalizeStub
);
rt: JSRuntime;
cx: JSContext;
global: JSObject;
implementation
{$R *.dfm}
function alertFunc(cx: JSContext; obj: JSObject; argc: JSUintn; argv: PJSValArray; out rval: jsval): JSBool; cdecl;
var
str: JSString;
msg: String;
i: Integer;
v: jsval;
begin
for i:=0 to argc-1 do
begin
v := argv^[i];
str := JS_ValueToString(cx, v);
if i<>0 then
msg := msg + ' ';
msg := msg + JS_GetStringBytes(str);
end;
ShowMessage(msg);
Result := True;
end;
var
funcs: array[0..1] of JSFunctionSpec = (
(
name: 'alert';
call: alertFunc;
),
(
)
);
procedure TForm1.FormCreate(Sender: TObject);
begin
rt := JS_NewRuntime($100000);
cx := JS_NewContext(rt, $1000);
global := JS_NewObject(cx, global_class, nil, nil);
JS_InitStandardClasses(cx, global);
JS_DefineFunctions(cx, global, PJSFunctionSpecArray(@funcs));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
//
end;
procedure TForm1.FormShow(Sender: TObject);
var
rval: jsval;
const
//script = 'function fact(n){if(n<=1)return 1;else return fact(n-1)*n;} fact(5);';
script = 'alert("hoge"); alert(1,2,3)';
begin
JS_EvaluateScript(cx, global, script, length(script), 'filename', 1, rval);
end;
end.
jsapi
ユニットはjsapi.h
等に書かれている関数プロトタイプと構造体の一部を記述したもの。
JS_NewRuntime
関数でスクリプト実行環境の初期化をする。引数はメモリ使用量。
JS_NewContext
関数はたぶんスレッドの初期化だと思う。
引数はJS_NewRuntime
で作った実行環境とスタックフレームのサイズ。
スタックフレームのサイズが小さいと深いネストでエラーになりやすい。ていうかなった。
JS_NewObject
でクラスの実体を作成し、JS_InitStandardClass
関数でクラスとスレッドを関連付ける。
どうもSpiderMonkeyの実装ではグローバル関数やグローバル変数というものは存在せず、グローバルクラス内のメソッドやメンバ変数として扱われるようだ。
で、JS_DefineFunctions
では実際にグローバルクラスにメソッドを追加している。
今回はalert
という関数を追加した。
関数の内容と記述方法はソース見たほうが早いので説明は省略する。
コードの実行はJS_EvaluateScript
で行う。
関数宣言などコードの即時実行を伴わないものは、JS_CompileScript
が使えそうな気がする。
ちなみに終了処理はしていない。 横着な実装だ。
メモ終わり。
コメントする