GraalJS の互換性

GraalJS は、ECMAScript に準拠した JavaScript 言語ランタイムです。このドキュメントでは、JavaScript で記述されたユーザーアプリケーション向けに提供されるパブリック API について説明します。

ECMAScript 言語準拠 #

GraalJS は、ECMAScript (ECMA-262) 仕様を実装しており、ECMAScript 2024 仕様 (第 15 版とも呼ばれる) と完全に互換性があります。新しい機能は、ECMAScript 2024 の一部として確定すると、GraalVM に頻繁に追加されます。詳細については、CHANGELOG.md を参照してください。ECMAScript 5 以降の古いバージョンは、設定オプションで有効にできます (番号の場合: --js.ecmascript-version=5、年の場合: --js.ecmascript-version=2024)。実稼働環境では、GraalJS の将来のバージョンで利用可能になると、仕様の新しいバージョンを使用するため、使用する ECMAScript バージョンを固定することを検討してください。

GraalJS は、JavaScript コアライブラリを表す、ECMAScript で指定されているグローバルスコープに次の関数オブジェクトを提供します: Array、ArrayBuffer、Boolean、DataView、Date、Error、Function、JSON、Map、Math、Number、Object、Promise、Proxy、Reflect、RegExp、Set、SharedArrayBuffer、String、Symbol、TypedArray、WeakMap、WeakSet。

追加のオブジェクトは、たとえば、--js.temporal のようにオプションで利用できます。利用可能なオプションのリストについては、js --help を実行してください。

これらの関数オブジェクトのいくつか、およびそのメンバーの一部は、特定のバージョンの仕様が実行に選択されている場合にのみ利用可能です。提供されるメソッドのリストについては、ECMAScript 仕様を調べてください。仕様に対する拡張機能は以下に指定します。

国際化 API (ECMA-402) #

GraalJS には、デフォルトで有効になっている ECMA-402 国際化 API の実装が付属しています (次のオプションを使用して無効にできます: --js.intl-402=false)。これには、次の拡張機能が含まれます。

  • Intl.Collator
  • Intl.DateTimeFormat
  • Intl.DisplayNames
  • Intl.ListFormat
  • Intl.Locale
  • Intl.NumberFormat
  • Intl.PluralRules
  • Intl.RelativeTimeFormat
  • Intl.Segmenter

toLocaleString などの他のいくつかの組み込みの機能も、ECMA-402 仕様に従って更新されます。

JavaScript モジュール #

GraalJS は、ECMAScript 6 以降で定義されているモジュールをサポートしています。この機能のサポートは引き続き拡大していることに注意してください。最新のすべての機能については、必ず最新の ECMAScript バージョンを使用してください。

ポリグロットの Source を介してモジュールをロードする場合、モジュールをロードしていることを指定するために、非公式の application/javascript+module MIME タイプを使用できます。ファイルから JavaScript コードをロードする場合は、モジュールが * .mjs * 拡張子のファイルからロードされていることを確認してください。import キーワードを使用したロードは、それによって制限されず、任意の拡張子のファイルから import できます。

互換性拡張 #

GraalJS では、他の JavaScript エンジンとの互換性のために、次のオブジェクトとメソッドが利用可能です。このようなメソッドの動作は、既存のすべてのエンジンのメソッドのセマンティクスと厳密に一致しない場合があることに注意してください。

言語機能 #

条件付きキャッチ句

js.syntax-extensions オプションが有効になっている場合、GraalJS は条件付きキャッチ句をサポートします。

try {
    myMethod(); // can throw
} catch (e if e instanceof TypeError) {
    print("TypeError caught");
} catch (e) {
    print("another Error caught");
}

グローバルプロパティ #

load(source)

  • 指定された JavaScript ソースコードをロード (解析および実行) します

ソースのタイプは次のいずれかです

  • String: 実行するソースファイルのパスまたは URL。
  • java.lang.URL: js.load-from-url オプションが true に設定されている場合、URL にソースコードの実行を問い合わせます。
  • java.io.File: ファイルを読み取ってソースコードを実行します。
  • JavaScript オブジェクト: オブジェクトに、それぞれソース名とコードを表す name プロパティと script プロパティが問い合わせられます。
  • その他すべてのタイプ: ソースは String に変換されます。

load はデフォルトで使用可能であり、js.load オプションを false に設定することで無効にできます。

print(...arg) および printErr(...arg)

  • 引数をコンソール (それぞれ stdoutstderr) に出力します
  • 可能な限り、人間が読みやすい出力を提供します

print および printErr はデフォルトで使用可能であり、js.print オプションを false に設定することで無効にできます。

console グローバルオブジェクトのメソッド

デバッグ目的でいくつかのメソッドを提供するグローバルな console オブジェクトが提供されます。これらのメソッドは、他のエンジンで提供されるものと同様の機能を提供しようとしますが、同一の結果を保証するものではありません。

GraalJS が Node.js モードで実行されている場合 (たとえば、js の代わりに node 実行可能ファイルが起動された場合)、これらのメソッドの動作が異なることに注意してください。Node.js は、代わりに使用される独自の実装を提供します。

  • console.log, console.info, および console.debug: print(...arg) のエイリアス
  • console.error および console.warn: print と同様ですが、エラー IO ストリームを使用します
  • console.assert(check, message): check が偽の場合に message を出力します
  • console.clear: 可能であればコンソールウィンドウをクリアします
  • console.count() および console.countReset(): 呼び出された回数をカウントして出力するか、このカウンターをリセットします
  • console.group および console.groupEnd: コンソールへの後続の出力のインデントを増減します
  • console.time(), console.timeLog(), および console.timeEnd(): それぞれタイマーを開始し、タイマーがアクティブになっている時間を表示するか、時間を表示してタイマーを停止します

console オブジェクトはデフォルトで使用可能であり、オプション js.consolefalse に設定することで無効にできます。

js シェルの追加グローバル関数 #

quit(status)

  • エンジンを終了し、指定されたステータスコードを返します

read(file)

  • file のコンテンツを読み取ります

結果は String として返されます。

引数 file のタイプは次のいずれかです

  • java.io.File: ファイルが直接使用されます。
  • その他すべてのタイプ: file は String に変換され、ファイル名として解釈されます。

readbuffer(file)

  • read 関数と同様に、file のコンテンツを読み取ります

結果は JavaScript の ArrayBuffer オブジェクトとして返されます。

readline()

  • 入力ストリームから 1 行の入力を読み取ります

結果は String として返されます。

Object #

Object.prototype.__defineGetter__(prop, func)

  • thisprop プロパティを getter 関数 func になるように定義します

この機能は、ほとんどの JavaScript エンジンで非推奨となっています。最近の ECMAScript バージョンでは、getter と setter が言語によってネイティブにサポートされています。

Object.prototype.__defineSetter__(prop, func)

  • thisprop プロパティを setter 関数 func になるように定義します

この機能は、ほとんどの JavaScript エンジンで非推奨となっています。最近の ECMAScript バージョンでは、getter と setter が言語によってネイティブにサポートされています。

Object.prototype.__lookupGetter__(prop)

  • __defineGetter__ で設定されたオブジェクトのプロパティ prop の getter 関数を返します

この機能は、ほとんどの JavaScript エンジンで非推奨となっています。最近の ECMAScript バージョンでは、getter と setter が言語によってネイティブにサポートされています。

Object.prototype.__lookupSetter__(prop)

  • __defineSetter__ で設定されたオブジェクトのプロパティ prop の setter 関数を返します

この機能は、ほとんどの JavaScript エンジンで非推奨となっています。最近の ECMAScript バージョンでは、getter と setter が言語によってネイティブにサポートされています。

Nashorn スクリプトモード #

GraalJS は、Nashorn エンジンによって提供されるものと互換性のあるスクリプトモードを提供します。これは、js.scripting オプションで有効になります。--experimental-options が設定されていることを確認してください

js --experimental-options --js.scripting=true

スクリプトモードでは、readFullyreadLine$ARG$ENV$EXEC など、いくつかのプロパティと関数がグローバルオブジェクトに追加されます。

以前に Nashorn または Rhino エンジンを対象としたコードで使用できる移行ガイドがあります。

GraalJS 拡張 #

Graal オブジェクト #

Graal オブジェクトは、グローバルオブジェクトのプロパティとして提供されます。これは、Graal 固有の情報を提供します。プロパティの存在は、GraalJS が現在の言語エンジンであるかどうかを識別するために使用できます

if (typeof Graal != 'undefined') {
    print(Graal.versionECMAScript);
    print(Graal.versionGraalVM);
    print(Graal.isGraalRuntime());
}

Graal オブジェクトは、オプション (js.graal-builtin=false) で無効にしない限り、デフォルトで GraalJS で使用可能です。

Graal.versionECMAScript

  • GraalJS ECMAScript 互換モードのバージョン番号 (年値) を提供します

Graal.versionGraalVM

  • 現在のエンジンが GraalVM で実行されている場合、GraalVM のバージョンを提供します

Graal.isGraalRuntime()

  • GraalJS が GraalVM 対応ランタイムで実行されているかどうかを示します
  • true の場合、ホットコードは Graal コンパイラによってコンパイルされ、高いピークパフォーマンスが得られます。
  • false の場合、GraalJS は Graal コンパイラによって最適化されず、通常はパフォーマンスが低下します。

Graal.setUnhandledPromiseRejectionHandler(handler) #

  • オプション (js.unhandled-rejections=handler) を使用する場合の、未処理の Promise リジェクトハンドラーを提供します。
  • ハンドラーは、2 つの引数 (rejectionReason、unhandledPromise) で呼び出されます。
  • Graal.setUnhandledPromiseRejectionHandler は、ハンドラーをクリアするために、nullundefined、または空の引数を指定して呼び出すことができます。

Java #

Java オブジェクトは、ホストクラスルックアップが許可されている場合にのみ利用可能です。Java ホストクラスとそのメンバーにアクセスするには、まず ホストアクセスポリシー によって許可され、ネイティブ実行可能ファイルから実行する場合は、ランタイムリフレクションに登録されている必要があります。

一部の関数では、Nashorn 互換モードを有効にする必要があることに注意してください (--js.nashorn-compat=true)。

Java.type(className)

Java.type は、指定された Java クラスをロードし、そのクラスの静的メンバー (たとえば、メソッドやフィールド) を持ち、new キーワードで新しいインスタンスを構築するために使用できる構築可能なオブジェクトを返します

var BigDecimal = Java.type('java.math.BigDecimal');
var point1 = new BigDecimal("0.1");
var two = BigDecimal.TWO;
console.log(point1.multiply(two).toString());

new 演算子で直接使用する場合、Java.type(...) を括弧で囲む必要があることに注意してください

console.log(new (Java.type('java.math.BigDecimal'))("1.1").pow(15));

Java.from(javaData)

Java.from は、Java データ構造 (Array、List) の浅いコピーを JavaScript 配列として作成します。

多くの場合、これは必要ありません。通常、JavaScript から Java データ構造を直接使用できます。

Java.to(jsData, javaType)

Java.to は、引数を Java タイプに変換します。

ソースオブジェクトjsDataは、JavaScript配列、またはlengthプロパティを持つ配列のようなオブジェクトであることが期待されます。ターゲットのjavaTypeは、String(例えば"int[]")または型オブジェクト(例えばJava.type("int[]"))のいずれかです。有効なターゲット型はJava配列です。ターゲット型が省略された場合、デフォルトでObject[]になります。

var jsArray = ["a", "b", "c"];
var stringArrayType = Java.type("java.lang.String[]");
var javaArray = Java.to(jsArray, stringArrayType);
assertEquals('class java.lang.String[]', String(javaArray.getClass()));
var javaArray = Java.to(jsArray);
assertEquals('class java.lang.Object[]', String(javaArray.getClass()));

JavaScriptの値がJava型に変換される必要がある場合、ECMAScriptで定義された変換メソッド(例えば、ToStringToDouble)が実行されます。情報が失われる変換は許可されず、TypeErrorが発生します。

Java.isJavaObject(obj)

  • objがJavaホストオブジェクトの場合、trueを返します
  • ネイティブJavaScriptオブジェクトや、他のポリグロット言語のオブジェクトの場合はfalseを返します

Java.isType(obj)

  • objJava.type()またはパッケージオブジェクトで取得された、Javaクラスのコンストラクタおよび静的メンバーを表すオブジェクトの場合、trueを返します。
  • その他のすべての引数に対してはfalseを返します

Java.typeName(obj)

  • objがJava型(isType(obj) === true)またはJavaのClassインスタンスを表す場合、objのJava Class名を返します
  • それ以外の場合はundefinedを返します

Java.isJavaFunction(fn)

  • fnがJava関数を表すJava言語のオブジェクトであるかどうかを返します
  • ネイティブJavaScript関数や他のポリグロット言語の関数を含む、他のすべての型に対してはfalseを返します

この関数は、Nashorn互換モード(--js.nashorn-compat=true)でのみ利用可能です。

Java.isScriptObject(obj)

  • objがJavaScript言語のオブジェクトであるかどうかを返します
  • Javaや他のポリグロット言語のオブジェクトを含む、他のすべての型に対してはfalseを返します

この関数は、Nashorn互換モード(--js.nashorn-compat=true)でのみ利用可能です。

Java.isScriptFunction(fn)

  • fnがJavaScript関数であるかどうかを返します
  • Java関数や他のポリグロット言語の関数を含む、他のすべての型に対してはfalseを返します

この関数は、Nashorn互換モード(--js.nashorn-compat=true)でのみ利用可能です。

Java.addToClasspath(location)

  • 指定された場所(.jarファイルまたはディレクトリパス文字列)をJavaのクラスパスに追加します

ポリグロット #

Polyglotオブジェクトの関数を使用すると、他のポリグロット言語の値とやり取りできます。

Polyglotオブジェクトは、js.polyglot-builtinオプションをfalseに設定して無効化しない限り、デフォルトで使用できます。

Polyglot.export(key, value)

  • JavaScriptのvalueを名前key(文字列)でポリグロットバインディングにエクスポートします
    function helloWorld() { print("Hello, JavaScript world"); }
    Polyglot.export("helloJSWorld", helloWorld);
    

ポリグロットバインディングにkeyで識別される値がすでに存在する場合、新しい値で上書きされます。valueは、任意の有効なポリグロット値である可能性があります。

  • keyが文字列でないか、または存在しない場合はTypeErrorをスローします

Polyglot.import(key)

  • key(文字列)で識別される値をポリグロットバインディングからインポートして返します
    var rubyHelloWorld = Polyglot.import("helloRubyWorld");
    rubyHelloWorld();
    

keyで識別される値をエクスポートした言語がない場合、undefinedが返されます。

  • keyが文字列でないか、または存在しない場合はTypeErrorをスローします

Polyglot.eval(languageId, sourceCode)

  • languageIdで識別されるインタプリタを使用して、sourceCodeを解析および評価します

sourceCodeの値は、文字列(または文字列に変換可能なもの)であることが期待されます。

  • 評価結果は、sourceCodeや評価される言語のセマンティクスに応じて返されます
    var pyArray = Polyglot.eval('python', 'import random; [random.uniform(0.0, 1.0) for _ in range(1000)]');
    

無効なlanguageIdが渡された場合、sourceCodeを言語で評価できない場合、または実行されたプログラムが例外をスローした場合は、例外が発生する可能性があります。

Polyglot.evalFile(languageId, sourceFileName)

  • languageIdで識別されるインタプリタを使用して、ファイルsourceFileNameを解析します

sourceFileNameの値は、現在のパスからアクセス可能なファイルを表す文字列(または文字列に変換可能なもの)であることが期待されます。

  • 実行可能なオブジェクト、通常は関数を返します
    var rFunc = Polyglot.evalFile('R', 'myExample.r');
    var result = rFunc();
    

無効なlanguageIdが渡された場合、sourceFileNameで識別されるファイルが見つからない場合、または言語が解析中に例外をスローした場合(構文エラーなどの解析時エラー)は、例外が発生する可能性があります。評価されたプログラムによってスローされる例外は、結果の関数が評価されるまでスローされません。

Polyglot.evalFile関数は、Polyglot組み込みが利用可能な場合、js.polyglot-evalfileオプションをfalseに設定して無効化しない限り、デフォルトで使用できます。また、js.debug-builtinが有効になっている場合も利用できます。

デバッグ #

  • js.debug-builtinオプションを指定してエンジンを起動する必要があります

Debugは、JavaScriptコードとJavaScriptエンジンのデバッグ機能を提供するGraalJS固有の関数オブジェクトです。このAPIは予告なしに変更される可能性があります。本番環境での使用は避けてください。

グローバル関数 #

printErr(...arg)

  • printと同じように動作します

唯一の違いは、デフォルトの出力ストリームの代わりに、エラー ストリームを使用して印刷されることです。

loadWithNewGlobal(source, arguments)

  • load関数と同様に動作します

関連する違いは、コードが新しいグローバルスコープ(ECMAScriptで定義されているレルム)で評価されることです。

ソースのタイプは次のいずれかです

  • java.lang.URL:URLから実行するソースコードがクエリされます。
  • JavaScriptオブジェクト:オブジェクトからnameプロパティとscriptプロパティがクエリされます。
  • その他すべてのタイプ: ソースは String に変換されます。

argumentsの値は、ロードされたコードの実行時に提供されます。

お問い合わせ