Mozilla.com

  1. MDC
  2. メインページ
  3. Embedding SpiderMonkey

◆◆◆ 翻訳中 ◆◆◆

このページは翻訳中です。
翻訳作業に参加する場合は、履歴にある翻訳者と連絡·調整してください。

ここではJavaScriptエンジンのC言語実装(SpiderMonkey)の概要を説明し、JSエンジンをあなたのアプリケーションにどのように埋め込むかを説明します。JSエンジンをアプリケーションに埋め込むとは、2つの大きなメリットがあります。 まず、スクリプトを使用しアプリケーションの自動化が実現できます。また、クロスプラットフォーム機能を提供するJSエンジンとJavaScriptを利用することで、プラットホーム依存性を排除できます。

サポートするJavaScriptのバージョン

JSエンジンはJS 1.0から1.4をサポートします。JS 1.3以上はECMAScript-262規格に従います。より基本的には、JSエンジンはJS構文と関数をふくむスクリプトを、パースし、コンパイルして実行します。エンジンはスクリプトの実行に必要な、データやオブジェクトのために、メモリを取得し、クリーンナップ(ガベレージコレクション=必要でなくなったデータやオブジェクトをメモリを解放)します。

How Do You Use the Engine?

一般に、JSエンジンは共用ライブラリとしてビルドされます。 例えば、WindowsとWindows NTではDLL、Unixでは共有ライブラリとして。 あなたは、アプリケーションにそれにリンクして、JSエンジンアプリケーションプログラミングインタフェース(API)呼び出します。 JSエンジンのAPIは以下の広いカテゴリにわたる機能を提供します:

  • データ型操作
  • ランタイム・コントロール
  • クラスとオブジェクトの作成と管理
  • 関数とスクリプトの実行
  • 文字列の操作
  • エラー・ハンドリング
  • セキュリティーコントロール
  • デバッグ機能

これらのカテゴリの内、ランタイム・コントロールやデータ型操作はあらゆるアプリケーションで必要です。例えば、すべてのJS関数を呼び出す前に、JS_NewRuntimeを実行して、JSエンジンを作成・初期化しなければなりません。対して、セキュリティコントロールなどは必要であれば使用することができる機能です。

How Does the Engine Relate to Applications?

JSエンジンはシステムの共用リソースです。 アプリケーションは、APIを呼び出すことで、JSエンジンに要求を伝えることができます。 エンジンは、順番に要求を処理し、値か状態情報を返します。

図 1.1

Image:Over1.gif

例えば、JavaScriptを利用して、ユーザを認証し、ユーザのアクセス権を設定するアプリケーションがあるとします。まず最初に、アプリケーションは、ユーザの名前、ID、アクセス権、など含んでいるカスタムJSオブジェクトを作成することでしょう。

この場合、アプリケーションはカスタム・オブジェクトを作成するために、JS_NewObjectを呼び出します。<!-In this case, your application's first request to the JS engine might be a call to JS_NewObject to create the custom object.-->JSエンジンは、オブジェクトを作成したら、そのポインタをアプリケーションに返します。 次に、アプリケーションは「オブジェクトを使用するスクリプト」を実行するために、JSエンジンを呼び出します。例えばあなたのアプリケーションは、ユーザ・オブジェクトを作成した後、スクリプトをコンパイルして実行するために、スクリプト・コードをJS_EvaluateScriptに渡すでしょう。 そのスクリプトは、ユーザの情報を確認し、他の機能を有効にするための設定をするものです。

実際には、アプリケーションとJSエンジンとの実際の図1.1で示されるよりいくらか複雑です。まずプラットホーム用のJSエンジンがビルドしないといけません。そして、JSエンジンを利用するコードではjsapi.hをincludeします。そして、アプリケーションは最初にJSランタイムを初期化します。

JSエンジンは初期化要求を受け取ると、JSランタイムのためにメモリを割り当てます。

図1.2

Image:Over2.gif

ランタイムは、あなたのアプリケーションで使用される変数、オブジェクト、およびコンテキストが維持されるスペースです。 コンテキストはJSエンジンによって使用されるスレッドのためのスクリプト実行状態です。 それぞれのスクリプトかスレッドには、それ自身のコンテキストがなければなりません。 一つのJSランタイムは、多くのコンテキスト、オブジェクト、および変数を含むことができます。

JSエンジンを呼び出すほぼすべての場合で、コンテキストを引数として必要とします。そのため、アプリケーションでランタイムを作った後、最初に実行しなければいけないことの1つがJS_NewContextによりコンテキストを少なくとも1つ作ることになります。実際にコンテキストをいくつ必要とするかは、アプリケーション内でスクリプトをいくつ使おうとしているかに決まります。アプリケーション内で同時に実行するスクリプト1つごとに、1つのコンテキストが必要になります。その一方、アプリケーションが実行中の任意の時点で実行されるスクリプトが1つだけであれば、コンテキストを1つ作り、そのコンテキストをスクリプトごとに再利用することもできます。

通常の場合、コンテキストを作ったあと、JSエンジンに最初から組みこまれているオブジェクトをJS_InitStandardClassesにより初期化することになります。 ほとんどのスクリプトで使われるArray, Boolean, Date, Math, Number, Stringが最初から組み込まれています。

アプリケーションは通常カスタムJSオブジェクトを使用します。カスタムJSオブジェクトは、アプリケーションの必要性に応じて作られるオブジェクトです。 カスタムオブジェクトには、アプリケーションを実行するために使われるデータ構造やメソッドに対応します。 カスタムJSオブジェクトを作るためには、オブジェクトに対応するJSクラスを実装し、JS_InitClassを呼び出すことによりランタイムに作成したクラスを登録し、 そのあと、JS_NewObjectを呼び出すことにより作成したカスタムオブジェクトのインスタンスを作る必要があります。 最後に、作成したオブジェクトがプロパティーを持つ場合には、JS_SetPropertyを呼び出すことにより、プロパティーのデフォルト値を設定する必要があるかも知れません。 オブジェクトを作る際には、JSエンジンに対して特定のコンテキストを渡すことになりますが、オブジェクトは、コンテキストとは独立にランタイムの中に存在します。 オブジェクトをアクセスするためには、任意のスクリプトと、任意のコンテキストを対応させることができます。図 1.3 は、スクリプトに対する、ランタイムと、コンテキストと、オブジェクトの関係を示しています。

Figure 1.3

Image:Over3.gif

図1.3 が示しているように、同一のオブジェクトをアクセスする場合でも、スクリプトとコンテキストは全く独立して存在できます。 アプリケーションは、オブジェクトにアクセスするとき、同一のランタイムに属しているのであれば、 オブジェクトに割り当てられていないコンテキストを使うことができます。あるコンテキストとオブジェクトを、特定の目的だけに予約しておきたいような場合には、 アプリケーション内で別々のランタイムを作って下さい。 1つは、共有のコンテキストとオブジェクトのためのランタイムであり、 もう1つは(必要に応じて複数も可能)、特定の目的のコンテキストとオブジェクト用のランタイムになります。

NOTE:あるコンテキストに、ある瞬間にアクセスできるスレッドはただ1つだけであることに注意。

エンジンをビルドする

アプリケーションでJSを使うには、JSエンジンを共有ライブラリとしてビルドしなければなりません。ほとんどの場合、自動的にエンジンがビルドできる ようにメイクファイルが作られています。

例えば、Unixの場合、JSのソースディレクトリには、Makefile.refというGNU make用のメイクファイルと、configディレクトリがあります。 config ディレクトリには、Makefile.refとともに使われる、 いろいろなプラットフォーム用の.mkファイルが用意されています。Windows NTの場合には、js.makというnmake ファイルが用意されています。

ソースディレクトリにあるreadmeファイルをチェックしてください。

What Are the Requirements for Engine Embedding?

アプリケーションでJavaScriptを使えるようにするためには、アプリケーションでエンジンを適切に呼び出す必要があります。 少なくとも次の5つの呼び出しを行う必要があります。

  1. #include "jsapi.h"をCのモジュールに追加し、コンパイラがエンジンの呼び出しを行えるようにします。JSエンジンを特別な方法で使うような場合に、他のJSのソースコードを呼び出す必要がある場合があります。 例えば、アプリケーションでデバッガを呼び出すような場合には、jsdbgapi.hをアプリケーションのモジュールでインクルードする 必要があります。 JSのソースコードの他のほとんどのヘッダファイルは、インクルードするべきではありません。他のヘッダファイルをインクルードすると リリースごとに変更する可能性があるエンジンの内部の実装に依存することになってしまいます。
  2. アプリケーションで利用する構造体と変数を定義して下さい。例えば、JSエンジンにスクリプトを渡そうと考えているのであれば、アプリケーションでスクリプトの テキストデータを格納する文字列を用意して下さい。構造体と変数は、jsapi.hで定義されているJSのデータ型を使って定義して下さい。
  3. JavaScriptで、アプリケーション特有のオブジェクトを作ってください。特に、アプリケーションでJS園児を使って処理の自動化を行うような場合には、 スクリプトで利用するアプリケーション特有のオブジェクトは、Cプログラムで使う構造体とメソッドに対応します。
  4. 組み込み済みのJSオブジェクトを初期化するコードやアプリケーションで利用するオブジェクトが利用できるように、JSエンジンのAPIと変数を適切に組み込んで下さい。
  5. ほとんどのJSエンジンのAPIは、戻り値を返します。戻り値が、0かNULLである場合には、エラーの種別を表します。このような戻り値が 0でない場合には、APIの呼び出しが成功したことを意味します。APIの呼び出しが成功した場合、戻り値は、アプリケーションが後で利用するために保存しておくべきオブジェクトへのポインタである場合が多いです。最低でも、アプリケーションでAPIの呼び出し後、どんな場合でも戻り値のチェックを行うべきです。

次に示すコードで、JSスクリプトを作る以外の、組み込みステップのほとんどを示しています。スクリプトを作り、JavaScript言語そのもののオブジェクトに関する 情報は、Client-Side JavaScript Guideを読んで下さい。サーバ側のオブジェクトに関しては、Server-Side JavaScript Guideを読んで下さい。

.
.
.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* include the JS engine API header */
#include "jsapi.h"
.
.
.

/* main function sets up global JS variables, including run time,
 * a context, and a global object, then initializes the JS run time,
 * and creates a context. */

int main(int argc, char **argv)
{
  int c, i;
  /*set up global JS variables, including global and custom objects */

  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;
  JSBool builtins;

  /* initialize the JS run time, and return result in rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);

  /* if rt does not have a value, end the program here */
  if (!rt)
    return 1;

  /* create a context and associate it with the JS run time */
  cx = JS_NewContext(rt, 8192);

  /* if cx does not have a value, end the program here */
  if (cx == NULL)
    return 1;

  /* create the global object here */
  glob = JS_NewObject(cx, clasp, NULL, NULL);

  /* initialize the built-in JS objects and the global object */
  builtins = JS_InitStandardClasses(cx, glob);

  .
  . 
  .

  return 0;

}

この例は、JSエンジンをアプリで使うために必要な、主要な部分を単純化したものです。より完全な例は、js.cを見て下さい。これは、JSエンジンのソースに ある、サンプルアプリケーションです。

Understanding Key Embedding Concepts

アプリケーションでJavaScriptを使う用にする場合、ほとんどの場合で、JS APIをつかう標準的な使い方に従うことになるでしょう。 本セクションは、アプリケーションに組み込む必要のあるAPIの呼び出し方について記述しています。

多くの場合、正しく組みオムためには、ある種のAPIを正しい順序で呼び出すことが重要です。例えば、JSランタイムを初期化した後に、他のAPIを呼びださなければ なりません。同様に、アプリケーションが終了する前に、JSランタイムを開放すべきです。従って、アプリケーションのmain関数は、JSランタイムの初期化で始まったあと アプリケーション固有の処理を行ったあと、JSランタイムの開放処理で終わるように作られるべきです。

int main(int argc, char **argv)
{
  int c, i;

  /*set up global JS variables, including global and custom objects */
  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;

  .
  .
  .

  /* initialize the JS run time, and return result in rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);

  /* if rt does not have a value, end the program here */
  if (!rt)
    return 1;

  .
  .
  .

  /* establish a context */
  cx = JS_NewContext(rt, 8192);

  /* if cx does not have a value, end the program here */
  if (cx == NULL)
    return 1;

  /* initialize the built-in JS objects and the global object */
  builtins = JS_InitStandardClasses(cx, glob);

  .
  .
  .

  /* include your application code here, including JS API calls
   * that may include creating your own custom JS objects. The JS
   * object model starts here. */

  .
  .
  .

  /* Before exiting the application, free the JS run time */
  JS_DestroyRuntime(rt);

この例で示したように、JSエンジンを組み込むアプリケーションは、JSランタイムをまずセットアップし、終了前に開放する責任があります。 一般的には、JSランタイムを初期化して開放するのは、アプリケーション内でJavaScriptを起動する主要なモジュールで実行するのが最も良い実装になるでしょう。

ランタイムを初期化した後、アプリケーションで利用するJSオブジェクトモデルを構築することになります。オブジェクトモデルとは、JSオブジェクト同士の関係を決めるものです。 JSオブジェクトは、もともと階層的に作られています。そのため、全てのJSオブジェクトは、デフォルトでは、グローバルオブジェクトに関係づけられています。 オブジェクトは、デフォルトで、グローバルオブジェクトから派生したものになります。標準的なJSクラスを初期化すると、グローバルオブジェクトが自動的に作られます。

builtins = JS_InitStandardClasses(cx, glob);

グローバルオブジェクトは、他のオブジェクトが継承する基本的なプロパティとメソッドを利用できるようにします。カスタムオブジェクトを作る際には、カスタムオブジェクトは、 グローバルオブジェクトで定義されているプロパティとメソッドを使うことができます。グローバルオブジェクトで定義されているデフォルトのプロパティとメソッドは、 デフォルトのママで使うことも、カスタムオブジェクトで再定義することもできます。

カスタムオブジェクトは、他の組み込み済みのJSオブジェクトを基にして実装することもできますし、他のカスタムオブジェクトを基に実装することができます。 いずれの場合でも、カスタムオブジェクトは、グローバルオブジェクトから始まる階層構造の中の親オブジェクトのプロパティとメソッドを継承します。 グローバルオブジェクトとカスタムオブジェクトに関する情報は、Initializing Built-in Global JS ObjectsCreating and Initializng Custom Objects.を参照して下さい。

ランタイムの管理

JSランタイムは、JSエンジンが使うコンテキスト、オブジェクト、JS関数とスクリプトに付随する変数のメモリ空間です。 JS関数やスクリプトを使馬えに、ランタイムの初期化を行う必要があります。ランタイムの初期化を行う、APIは、JS_NewRuntimeです。 JS_NewRuntimeの引数は1つであり、ガーベージコレクションが発生する前にランタイムに割り当てる最大のバイト数を符号なし整数で指定します。 例えば、

 rt = JS_NewRuntime(8L * 1024L * 1024L);

この例が示すように、JS_NewRuntimeは、作られたランタイムへのポインタを返り値として返します。返り値が、NULLではない場合には、ランタイムの作成に成功したことを示します。

通常の場合、1つのアプリケーションに、1つだけランタイムを必要とします。しかし、必要に応じてJS_NewRuntime を呼び出し、戻り値を別のポインタに格納することにより、複数のランタイムを作ることもできます。

JSランタイムが必要ではなくなったときには、ランタイムを破棄して、ランタイムが使っていたメモリ資源を他のアプリケーションが使えるようにするべきです。 アプリケーション内でJSをどのように使うかによって、使い終わったらすぐにランタイムを破棄することもできますし、ランタイムをアプリケーションの終了時まで破棄せずに とっておくこともできます。何れの場合でも、不要になったランタイムをを開放するには、JS_DestroyRuntimeを使います。 この関数は、破棄するランタイムへのポインタを引数としてとります。

 JS_DestroyRuntime(rt);

複数のランタイムを使う場合には、それぞれのランタイムをアプリケーションの終了前に開放して下さい。

コンテクストの管理

ほとんどのJS APIは、引数としてに、コンテキストを渡す必要があります。コンテキストは、JavaScriptエンジン内で、スクリプトに対応します。 エンジンは、スクリプトを実行するスレッドに、コンテキスト情報を渡します。同時に実行されるスクリプトには、スクリプトごとにコンテキストが割り当てられなければ なりません。スクリプトが実行を完了したときには、コンテキストは不要になり、コンテキストは新しいスクリプトに割り当てたり、開放したりすることができます。

スクリプトを実行するために新しいコンテキストを作るときには、JS_NewContextを使います。この関数は、2つの引数をとります。 1つは、コンテキストと関連づけるランタイムへのポインタであり、もう1つは、コンテキストのスタックに割り当てるバイト数である。 コンテキストの作成に成功した場合には、新しくできあがったコンテキストへのポインタを返します。例:

 JSContext *cx;
 .
 .
 .
 cx = JS_NewContext(rt, 8192);

ランタイムは、呼び出し前に作っておかなければなりません。コンテキストを作る際に指定するスタックの大きさは、コンテキストを使って実行するスクリプトによって作られる変数やオブジェクトに合うだけの大きさがなければなりません。コンテキストを割り当てたり管理したりする際には、オーバヘッドがあるため、次のような事柄に注意を必要とします。

  1. アプリケーション内で、ある時点で必要とする数だけ、コンテキストを作成する
  2. アプリケーションで使うかも知れないのであれば、コンテキストをとっておき、必要に応じてコンテキストを破棄したり、再作成したりしないこと

コンテキストが不要になったとき、割り当てられていたメモリ資源を開放し他のアプリケーションが使えるように、コンテキストを破棄すべきです。 アプリケーションでのコンテキストの使い方により、コンテキストが不要になったらすぐに破棄することもできますし、また、アプリケーションが終了するときまでコンテキストを破棄せずにとっておくこともできます。どちらの場合でも、JS_DestroyContextを使って、不要になったときには、コンテキストを破棄します。 この関数には、破棄するコンテキストへのポインタを引数として渡します。

 JS_DestroyContext(cx);

アプリケーションが複数のランタイムを作るときには、アプリケーションの使っているコンテキストが、どのランタイムで使われているかを知る必要がでてくる場合がある。 このような場合には、引数としてコンテキストを渡してJS_GetRuntimeを呼び出してください。JS_GetRuntimeは、対応するランタイムへのポインタを返します。

 rt = JS_GetRuntime(cx);

コンテキストを作るときには、コンテキストを使うスクリプトによって作られる変数やオブジェクトを格納するためのスタック領域を割り当てます。 スタック領域の使用量を最小にしながら、コンテキストに大容量のデータを格納することもできます。JS_SetContextPrivateを呼ぶことで、コンテキストに プライベートデータへのポインタを格納できます。データにアクセスするためにプライベートポインタを取得するときには、JS_GetContextPrivateを呼んでください。プライベートデータの構築や管理は、アプリケーションで行う必要があります。

プライベートデータを作りコンテキストに関連付けるためには、次のことを行ってください。

  1. C 言語の void ポインタ変数としてプライベートデータをつくる
  2. プライベートデータを格納するコンテキストと、プライベートデータを引数として[[JS_SetContextPrivate[[を呼ぶ

例:

 JS_SetContextPrivate(cx, pdata);

後でプライベートデータを取得する場合には、コンテキストを引数としてJS_GetContextPrivateを呼び出してください。 この関数は、プライベートデータへのポインタを返します。

 pdata = JS_GetContextPrivate(cx);

JSのグローバルオブジェクトの初期化

JavaScriptエンジンには、開発が簡単にできるようにするため、組み込み済みのオブジェクトが実装されています。 例えば、Arrayオブジェクトを使うことで、配列を簡単に作って使うことができるようになっています。 また、Dateオブジェクにより、日付を統一的に扱えるようになっています。エンジンに実装されている組み込み済みのオブジェクトのリストは、 JS_InitStandardClassのエントリーを参照すると見つかります。

JSエンジンは、関数オブジェクトとグローバルオブジェクトを使います。一般的には、グローバルオブジェクトは、アプリケーションの中で グローバルオブジェクト以外のすべてのオブジェクトとグローバル変数のためのデフォルトのスコープの役割を果たします。 アプリケーション用のオブジェクトを作る前に、グローバルオブジェクトの初期化を行うことになるでしょう。関数オブジェクトは、オブジェクトの コンストラクタに利用されます。

JS_InitStandardClassessを呼ぶことで、グローバルオブジェクト、関数オブジェクトと組み込み済みのエンジン用の オブジェクトが初期化され、アプリケーションでこれらのオブジェクトを使うことができるようになります。

 JSBool builtins;
 .
 .
 .
 builtins = JS_InitStandardClasses(cx, glob);

JS_InitStandardClasses を呼び出すと、初期化が成功したかどうかをJSのブール型で返します。

アプリケーションは、別のグローバルオブジェクトを使うこともできます。例えば、Netscape Navigatorは、Netscape Navigator専用のグローバルオブジェクトである、windowオブジェクトを使っています。アプリケーションでグローバルオブジェクトを変更するときには、 JS_SetGlobalObjectを使ってください。より詳しい情報は、JS_GetGlobalObjectの項を参照してください。

Creating and Initializing Custom Objects

内蔵されているオブジェクトと共に、カスタムJSオブジェクトを作成して、初期化して、使用することができます。 あなたがあなたのアプリケーションを自動化するために、JSエンジンを使用しているなら、特に必要でしょう。 カスタムJSオブジェクトは、ダイレクトに、またはそれらはインタフェースとして、プログラム・サービスを提供することができます。例えば、ネットワークアクセスを扱ったり、データベース・サービス扱ったりするかもしれません。 また、データを反映するJSオブジェクトは、オブジェクト指向インタフェースを、厳密に言うとオブジェクト指向でないCコードに提供するかもしれません。 そのようなカスタムオブジェクトはインタフェースとしてアプリケーション自体に作用します、アプリケーションからユーザと、それを返す前の受信と処理ユーザ入力からアプリケーションまで値を通過して。 また、そのようなオブジェクトは、アクセスコントロールをアプリケーションの基本的な機能に提供するのに使用されるかもしれません。

カスタムJSオブジェクトを作成するには、2つの方法があります:

  • オブジェクト(のプロパティーやメソッドやコンストラクタ)を作成するJSスクリプトを書き、アプリケーションの実行時にそのスクリプトを実行します。
  • アプリケーションに、オブジェクトのメソッドとプロパティーを定義するコードを埋め込みます。そしてエンジンをコールし、新しいオブジェクトを初期化します。さらにコールして、オブジェクトのプロパティーを設定します。 この方法の利点は、あなたのアプリケーションが直接オブジェクトの埋め込みを操るネイティブのメソッドを含むことができるということです。

どちらの場合でも、ガベレージコレクションでオブジェクトが消えないようにしたいならば、JS_AddRootJS_AddNamedRootを呼ぶことによって、オブジェクトを根づかせなければなりません。

スクリプトからオブジェクトを作る

One reason to create a custom JS object from a script is when you only need an object to exist as long as the script that uses it is executing. To create objects that persist across script calls, you can embed the object code in your application instead of using a script.

NOTE: 永続的なオブジェクトを作るときにもスクリプトを使うことができます。

スクリプトを使ってカスタムオブジェクトを作るには:

  1. オブジェクトを定義し、specしてください。つまり、オブジェクトが何をしようとしているか?オブジェクトのメンバ(プロパティ)は何か?オブジェクトのメソッド(関数)は何か? オブジェクトは実行時にコンストラクタを必要とするか?を指定します。
  2. そのようなオブジェクトを定義して、オブジェクトを作成するようなコードを作ってください。
  3. 例:

         function myfun(){
           var x = newObject();
           .
           .
           .
         }
    

    NOTE: JavaScriptを使ったobject scriptingは、アプリケーションにJSエンジンを組み込むという話とは別の話題となります。 そのためobject scriptingの情報については、Client-Side JavaScript GuideServer-side JavaScript Guideをご覧ください。

    アプリケーションの中で、スクリプトをコンパイルし実行するために適切にJSエンジンを呼び出すようにしてください。呼び出し方には、2種類の方法があります。1.) JS_EvaluateScriptJS_EvaluateUCSScriptを使ってコンパイルし実行する方法.

    2.) JS_CompileScriptJS_CompileUCSScriptを使って、一度スクリプトをコンパイルし、JS_ExecuteScriptを使って繰り返し実行する方法。"UC"がついている方は、UNICODEでエンコードされているスクリプトのために用意されています。

スクリプトを使って作ったオブジェクトは、スクリプトが実行されている間だけ利用できるようにもできますし、スクリプトの実行が終わったあとも利用できるようにもできます。 普通は、スクリプトの実行が終わると、オブジェクトは破棄されます。多くの場合、この動作がアプリケーションで必要となる動作です。その一方、複数のスクリプトを動かしている 間や、あるいは、 アプリケーションが動き続けている間にも、オブジェクトが破棄されずに残っていてほしいこともあるでしょう。そのような場合には、アプリケーションにオブジェクトを作る コードを直接組み込むか、グローバルオブジェクトが存在している間、オブジェクトが破棄されないように、オブジェクトをグローバルオブジェクトにしておく必要があります。

アプリケーションにカスタムオブジェクトを組み込む

オブジェクトが永続的に存在していることが求められる場合や、オブジェクトが複数のスクリプトの実行中にも利用できるようになっている方が望ましいときには、アプリケーションにカスタムJSオブジェクトを組み込むと、便利です。例えば、ユーザIDとアクセス権をあらわすようなオブジェクトがアプリケーションのライフタイム中に必要となる場合です。 スクリプト内でユーザIDとアクセス権をチェックする必要ができるたびに、オブジェクトを 作るのと比較して、カスタムオブジェクトを作ってアプリケーションに組み込んで、1度利用できるようにしておくと、実行時のオーバヘッドと実行時間を減らすことができます。

アプリケーションにカスタムオブジェクトを組み込む1つの方法は次の通りです:

  1. JSPropertySpecデータ型を作りオブジェクトのプロパティ情報にします。プロパティ情報には、プロパティーの名前と、get/set メソッドが入ります。
  2. JSFunctionSpecデータ型を作り、オブジェクトのメソッドとして使えるようにします。
  3. オブジェクトのメソッドを呼び出したときに実際に実行されるC言語の関数を作ります。
  4. JS_NewObjectJS_ConstructObjectを呼び、オブジェクトのインスタンスを作ります。
  5.  JS?DefineFunctionsを呼び、オブジェクトのメソッドを作ります。
  6. JS_DefinePropertiesを呼び、オブジェクトのプロパティを作ります。

永続的に存在するカスタムJSオブジェクトは、このオブジェクトの存在を必要とする他のコードが実行できるようにするため、アプリケーションの先頭付近におくべきです。 カスタムオブジェクトのインスタンスを作り、使えるようにするための組み込みエンジンの呼び出しを行う部分も、オブジェクトの存在を必要とする他のコードより前に 実行するべきです。

NOTE: 多くの場合により簡単にカスタムオブジェクトを作る方法として、JS_DefineObjectを使ってオブジェクトを作る方法もあります。オブジェクトを 作った後、繰り返しJS_SetPropertyを呼び、オブジェクトにプロパティを追加します。オブジェクトを定義するより詳しい方法については、JS_DefineObjectを参照ください。オブジェクトにプロパティーを追加する方法については、JS_SetPropertyをご覧ください。

Providing Private Data for Objects

コンテキストでできたのと同様に、オブジェクトのデータ構造自体にデータを保存せずに、オブジェクトに大きなデータを関連づけることができます。 JS_SetPrivateを使うことでオブジェクトのプライベートデータに、ポインタを格納できます。また、プライベートデータに格納してあるデータに アクセスするためにポインタを取得するには、JS_GetPrivateを呼び出して下さい。アプリケーションは、オプションで利用できるプライベートデータを 作成し、管理する責務を持ちます。

プライベートデータを作成し、オブジェクトに関連づけるには:

  1. プライベートデータを通常のC言語のvoid ポインタ変数として作成します。
  2. JS_SetPrivate関数を呼び、プライベートデータと関連づけるオブジェクトと、プライベートデータ自身のポインタを指定して、JS_SetPrivate関数を呼びます。

例:

 JS_SetPrivate(cx, obj, pdata);

データを後で使うためには、オブジェクトを引数としてJS_GetPrivateを呼びます。この関数は、オブジェクトの婦リベートデータへのポインタを返します。

 pdata = JS_GetPrivate(cx, obj);

Handling Unicode

現在のJSエンジンは、JS関数を含むスクリプトを処理する多くのAPIで、UNICODEを扱うことができます。 これらの関数は、UNICODEでエンコードされたスクリプトを直接エンジンに渡し、コンパイルして実行することができます。 次の表は、従来からある関数とそのUNICODE版の一覧です。

Standard Function Unicode-enabled Function
JS_DefineProperty JS_DefineUCProperty
JS_DefinePropertyWithTinyId JS_DefineUCPropertyWithTinyId
JS_LookupProperty JS_LookupUCProperty
JS_GetProperty JS_GetUCProperty
JS_SetProperty JS_SetUCProperty
JS_DeleteProperty2 JS_DeleteUCProperty2
JS_CompileScript JS_CompileUCScript
JS_CompileScriptForPrincipals JS_CompileUCScriptForPrincipals
JS_CompileFunction JS_CompileUCFunction
JS_CompileFunctionForPrincipals JS_CompileUCFunctionForPrincipals
JS_EvaluateScript JS_EvaluateUCScript
JS_EvaluateScriptForPrincipals JS_EvaluateUCScriptForPrincipals
JS_NewString JS_NewUCString
JS_NewStringCopyN JS_NewUCStringCopyN
JS_NewStringCopyZ JS_NewUCStringCopyZ
JS_InternString JS_InternUCString
-- JS_InternUCStringN

UNICODE版の関数は、同じ名前のUNICODE版ではない関数とまったく同じように動作します。ただし、UNICODE版ではない関数は、char *を引数としてとりますが、UNICODE版は、jschar *を引数として使います。

Working with JS Data Types

JavaScriptでは、独自の型を定義しています。JavaScriptの型の中には、直接C言語の型に対応しているものもあります。 直接C言語の型に対応していないような、JSObjectjsdoubleや、JSStringなどの 型は、JavaScriptに特有のものです。

一般的には、アプリケーションで使う型は、C言語でもそうするように、宣言する必要があります。しかし、JSエンジンは、格納するのに1ワード 以上の領域を必要とするJSObjectや,jsdoubleJSStringなどは、別々に 管理します。エンジンは定期的にこれらの変数が、使われているかどうかを確認し、使わ|