JavaScriptの互換性

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

ECMAScript言語コンプライアンス

GraalVM JavaScriptには、ECMAScript (ECMA-262)仕様の規定に従ってJavaScriptが実装されています。ECMAScript 2022仕様(13エディションまたはES13と呼ばれることもある)と完全な互換性があります。ECMAScript 2023に組み込まれたことが確認された新機能は、GraalVMに頻繁に追加されています。詳細は、CHANGELOG.mdを参照してください。ECMAScript 5以降の旧バージョンは、構成フラグ(番号: --js.ecmascript-version=5、または年: --js.ecmascript-version=2019)を使用して有効にできます。本番設定では、必要に応じて固定のECMAScriptバージョンを使用するよう指定することを検討してください。GraalVM JavaScriptの将来のバージョンでは、新しいバージョンの仕様が使用可能になった時点でその仕様が使用されるためです。

GraalVM JavaScriptでは、ECMAScriptで指定されたグローバル・スコープでJavaScriptコア・ライブラリを表す関数オブジェクト(Array、ArrayBuffer、Boolean、DataView、Date、Error、Function、JSON、Map、Math、Number、Object、Promise、Proxy、Reflect、RegExp、Set、SharedArrayBuffer、String、Symbol、TypedArray、WeakMapおよびWeakSet)が提供されています。

追加のオブジェクトは、Intl (フラグ: --js.intl-402)などのフラグで使用できます。使用可能なフラグのリストを表示するには、js --helpまたはjs --help:languagesを実行します。

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

国際化API (ECMA-402)

国際化API実装(https://tc39.github.io/ecma402を参照)は、--js.intl-402=trueフラグを使用してアクティブ化できます。ネイティブ・モード(デフォルト・オプション)で実行する場合は、--vm.Dcom.ibm.icu.impl.ICUBinary.dataPath=$GRAAL_VM_DIR/jre/languages/js/icu4j/icudtオプションを使用してICUデータ・ディレクトリへのパスも指定する必要があります。$GRAAL_VM_DIRは、GraalVMのインストール・ディレクトリです。JVMモード(--jvmフラグを使用)で実行する場合は、ICUデータの場所を前述のオプションで指定できますが、必須ではありません。

国際化APIをアクティブ化すると、次の組込み機能を使用できるようになります:

他のいくつかの組込み機能も、前述の仕様に従って更新されます。

JavaScriptモジュール

GraalVM JavaScriptは、ECMAScript 6以降で定義されているモジュールをサポートしています。この機能のサポートは徐々に拡張されていることに留意してください。必ず最新のすべての機能に最新のECMAScriptバージョンを使用してください。

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

互換性拡張機能

GraalVM JavaScriptでは、他のJavaScript実行エンジンとの互換性確保のために、次のオブジェクトおよびメソッドを使用できます。このようなメソッドの動作は、既存のすべてのエンジンのメソッドのセマンティクスと厳密に一致しない場合があります。

言語機能

条件付きcatch句

GraalVM JavaScriptでは、js.syntax-extensionsオプションが有効な場合、条件付きcatch句がサポートされます:

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

グローバル・プロパティ

load(source)

ソースの型は次のいずれかです:

loadはデフォルトで使用可能であり、js.loadオプションをfalseに設定することで非アクティブ化できます。

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

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

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

デバッグ用に複数のメソッドを提供するグローバルなconsoleオブジェクトが用意されています。これらのメソッドは、他のエンジンと可能なかぎり同じ機能を提供するように設計されていますが、必ずしも同一の結果が保証されるわけではありません。

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

consoleオブジェクトはデフォルトで使用可能であり、js.consoleオプションをfalseに設定することで非アクティブ化できます。

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

quit(status)

read(file)

結果は文字列として返されます。

引数fileの型は次のいずれかです:

readbuffer(file)

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

readline()

結果は文字列として返されます。

Object

Object.prototype.__defineGetter__(prop, func)

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

Object.prototype.__defineSetter__(prop, func)

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

Object.prototype.__lookupGetter__(prop)

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

Object.prototype.__lookupSetter__(prop)

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

Nashornスクリプト・モード

GraalVM JavaScriptには、Nashornエンジンに備わっているものと互換性のあるスクリプト・モードが用意されています。これは、js.scriptingオプションを使用して有効にします。必ず--experimental-optionsを設定してください:

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

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

これまでNashornエンジンまたはRhinoエンジンにターゲット指定していたコードを移行できるように、移行ガイドが用意されています。

GraalVM JavaScript拡張機能

Graalオブジェクト

Graalオブジェクトは、グローバル・オブジェクトのプロパティとして提供されています。これは、Graal固有の情報を示します。このプロパティの有無で、GraalVM JavaScriptエンジンが現在の言語エンジンであるかどうかを識別できます:

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

Graalオブジェクトは、オプション(js.graal-builtin=false)によって非アクティブ化しないかぎり、デフォルトでGraalVM JavaScriptで使用できます。

Graal.versionECMAScript

Graal.versionGraalVM

Graal.isGraalRuntime()

Graal.setUnhandledPromiseRejectionHandler(handler)

Java

Javaオブジェクトは、エンジンがJVMモード(--jvmフラグ)で起動された場合にのみ使用できます。

一部の関数ではNashorn互換性モード・フラグを設定する必要があることに注意してください。GraalVMでは、このフラグは次のように設定できます:

js --jvm --experimental-options --js.nashorn-compat=true

Java.type(className)

Java.from(javaData)

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

Java.to(jsData, toType)

ソース・オブジェクトjsDataは、JavaScript配列またはlengthプロパティを持つオブジェクトである必要があります。ターゲットtoTypeは、文字列(例: "int[]")または型オブジェクト(例: Java.type("int[]"))のいずれかです。有効なターゲット型はJava配列です。ターゲット型の指定がなければ、Object[]とみなされます:

var jsArr = ["a", "b", "c"];
var strArrType = Java.type("java.lang.String[]");
var javaArr = Java.to(jsArr, strArrType);
assertEquals('class java.lang.String[]', String(javaArr.getClass()));

ECMAScriptで定義されている変換メソッド(ToStringToDoubleなど)は、JavaScript値をJava型に変換する必要がある場合に実行されます。非可逆変換は許可されていないため、TypeErrorになります。

Java.isJavaObject(obj)

Java.isType(obj)

Java.typeName(obj)

Java.isJavaFunction(fn)

この関数には、Nashorn互換性モード・フラグが必要です。

Java.isScriptObject(obj)

この関数には、Nashorn互換性モード・フラグが必要です。

Java.isScriptFunction(fn)

この関数には、Nashorn互換性モード・フラグが必要です。

Java.addToClasspath(location)

ポリグロット

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

Polyglotオブジェクトは、js.polyglot-builtinオプションをfalseに設定することで非アクティブ化しないかぎり、デフォルトで使用可能です。

Polyglot.export(key, value)

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

Polyglot.import(key)

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

Polyglot.eval(languageId, sourceCode)

sourceCodeの値は、文字列(または文字列に変換可能)である必要があります。

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

Polyglot.evalFile(languageId, sourceFileName)

sourceFileNameの値は、現在のパスによって到達可能なファイルを表す文字列(または文字列に変換可能)である必要があります。

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

Polyglot.evalFile関数は、js.polyglot-evalfileオプションをfalseに設定することで非アクティブ化しないかぎり、Polyglot組込み機能が使用可能であればデフォルトで使用可能です。また、js.debug-builtinがアクティブ化されている場合にも使用可能です。

デバッグ

Debugは、JavaScriptコードおよびGraalVM JavaScriptコンパイラのデバッグ機能を提供するGraalVM JavaScript固有の関数オブジェクトです。このAPIは予告なしに変更される場合があります。本番用には使用しないでください。

グローバル関数

printErr(...arg)

唯一の違いは、デフォルトの出力ストリームではなく、エラー・ストリームが出力に使用されることです。

loadWithNewGlobal(source, arguments)

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

ソースの型は次のいずれかです:

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