残念ながら、Errandir のソリューションは、プロパティの名前を取得したいオブジェクトにアクセスするために使用できるグローバル変数の名前を知っている場合にのみ機能します。keys
メソッドをオブジェクトに追加し、後でJSObject
のcallメソッドを使用して呼び出すには、この名前を知っている必要があります。もちろん、オブジェクトのグローバル名があれば、それを Java に渡すことができます。このソリューションは、特にグローバル コンテキストでオブジェクトを参照できない場合は、あまり良くありません。
別の方法として、すべての作業を行うと仮定して、コメントでthis
ofJSObject
のevalメソッドを使用することを提案しました。そして、そうです。しかし、大きな失望は、Mozilla Firefox と Opera でしか期待どおりに動作しないことです。Internet Explorer 9 および Google Chrome (Windows 7 および Ubuntu 12.04 LTS でテスト済み) ではthis
、eval
メソッドの は常にアプレットのドキュメント ウィンドウを参照し、どの JavaScript オブジェクトJSObject
インスタンスが実際に表すかを無視します。これがバグなのか、単にLiveConnectがこれらのブラウザーでサポートされていないのか、私にはわかりません。
良いニュースは、call
のメソッドがJSObject
適切なコンテキストで指定された関数を実行することです。それを念頭に置いて、JavaScript オブジェクトのプロパティの名前のリストを取得する方法を最終的に見つけました。eval
アイデアは、メソッドを使用してグローバル コンテキストで一時的な関数を定義することです。この関数は、プロパティを取得したい JavaScript オブジェクトを受け取り、これらのプロパティの名前を配列として返す必要があります。その後、関連する JavaScript オブジェクトの Java 表現を渡すJSObject
のメソッドを介して一時関数を呼び出すことができます (以下のメソッドまたは質問で聞こえるように)。最後に、一時的な機能を削除できます。call
jsObject
args
public static ArrayList<String> getJsObjectPropertiesNames(Applet applet, JSObject jsObject) {
if (applet == null || jsObject == null)
return null;
// Retrieving global context - a JSObject representing a window applet belongs to
JSObject globalContext;
try {
globalContext = JSObject.getWindow(applet);
}
catch (JSException ex) {
return null;
}
// Checking whether passed object is not an array
try {
jsObject.getSlot(0);
return null;
}
catch (JSException e) {
}
String keysFunctionName = String.format("_getKeys%d", Calendar.getInstance().getTimeInMillis());
jsObject.eval("window['" + keysFunctionName + "'] = function(jsObject) { return Object.keys(jsObject) }");
JSObject propertiesNamesJsObject = (JSObject)globalContext.call(keysFunctionName, new Object[] { jsObject });
jsObject.eval("delete(window['" + keysFunctionName + "'])");
ArrayList<String> propertiesNames = new ArrayList<>();
try {
int slotIndex = 0;
while (true) {
Object propertyName = propertiesNamesJsObject.getSlot(slotIndex);
if (propertyName instanceof String)
propertiesNames.add((String)propertyName);
slotIndex++;
}
}
catch (JSException e) {
}
return propertiesNames;
}