This commit is contained in:
nboyd%atg.com 2000-09-11 15:12:04 +00:00
Родитель f5199e9faa
Коммит cd2482f9f2
7 изменённых файлов: 313 добавлений и 217 удалений

Просмотреть файл

@ -1,5 +1,5 @@
// The Java "NervousText" example ported to JavaScript.
// Compile using java org.mozilla..javascript.tools.jsc.Main -extends java.applet.Applet -implements java.lang.Runnable NervousText.js
// Compile using java org.mozilla.javascript.tools.jsc.Main -extends java.applet.Applet -implements java.lang.Runnable NervousText.js
/*
Adapted from Java code by
Daniel Wyszynski
@ -23,9 +23,9 @@ var counter =0;
var threadSuspended = false; //added by kwalrath
function init() {
resize(150,50);
setFont(new Font("TimesRoman",Font.BOLD,36));
s = getParameter("text");
this.resize(150,50);
this.setFont(new Font("TimesRoman",Font.BOLD,36));
s = this.getParameter("text");
if (s == null) {
s = "Rhino";
}
@ -47,7 +47,7 @@ function stop() {
function run() {
while (killme != null) {
try {Thread.sleep(100);} catch (e){}
repaint();
this.repaint();
}
killme = null;
}

Просмотреть файл

@ -67,7 +67,13 @@ public class JavaAdapter extends ScriptableObject {
}
return NativeJavaObject.coerceType(c, result);
}
public static Scriptable setAdapterProto(Scriptable obj, Object adapter) {
Scriptable res = ScriptRuntime.toObject(ScriptableObject.getTopLevelScope(obj),adapter);
res.setPrototype(obj);
return res;
}
public static Object js_JavaAdapter(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
throws InstantiationException, NoSuchMethodException,
@ -107,7 +113,7 @@ public class JavaAdapter extends ScriptableObject {
Class[] ctorParms = { Scriptable.class };
Object[] ctorArgs = { obj };
Object v = adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
return cx.toObject(v, ScriptableObject.getTopLevelScope(ctorObj));
return setAdapterProto(obj,v);
}
public static Class createAdapterClass(Context cx, Scriptable jsObj,
@ -120,6 +126,9 @@ public class JavaAdapter extends ScriptableObject {
ClassFileWriter cfw = new ClassFileWriter(adapterName,
superClass.getName(),
"<adapter>");
cfw.addField("delegee", "Lorg/mozilla/javascript/Scriptable;",
(short) (ClassFileWriter.ACC_PUBLIC |
ClassFileWriter.ACC_FINAL));
cfw.addField("self", "Lorg/mozilla/javascript/Scriptable;",
(short) (ClassFileWriter.ACC_PUBLIC |
ClassFileWriter.ACC_FINAL));
@ -174,7 +183,7 @@ public class JavaAdapter extends ScriptableObject {
// has a property of the same name, then an override is intended.
boolean isAbstractMethod = Modifier.isAbstract(mods);
if (isAbstractMethod ||
(jsObj != null && jsObj.has(method.getName(), jsObj)))
(jsObj != null && ScriptableObject.getProperty(jsObj,method.getName()) != Scriptable.NOT_FOUND))
{
// make sure to generate only one instance of a particular
// method/signature.
@ -201,32 +210,34 @@ public class JavaAdapter extends ScriptableObject {
// Generate Java methods, fields for remaining properties that
// are not overrides.
Object[] ids = jsObj.getIds();
for (int j=0; j < ids.length; j++) {
if (!(ids[j] instanceof String))
continue;
String id = (String) ids[j];
if (generatedMethods.containsKey(id))
continue;
Object f = jsObj.get(id, jsObj);
int length;
if (f instanceof Scriptable) {
Scriptable p = (Scriptable) f;
if (!(p instanceof Function))
for (Scriptable o = jsObj; o != null; o = (Scriptable)o.getPrototype()) {
Object[] ids = jsObj.getIds();
for (int j=0; j < ids.length; j++) {
if (!(ids[j] instanceof String))
continue;
length = (int) Context.toNumber(
ScriptableObject.getProperty(p, "length"));
} else if (f instanceof FunctionNode) {
length = ((FunctionNode) f).getVariableTable().getParameterCount();
} else {
continue;
}
Class[] parms = new Class[length];
for (int k=0; k < length; k++)
parms[k] = Object.class;
generateMethod(cfw, adapterName, id, parms, Object.class);
}
String id = (String) ids[j];
if (generatedMethods.containsKey(id))
continue;
Object f = o.get(id, o);
int length;
if (f instanceof Scriptable) {
Scriptable p = (Scriptable) f;
if (!(p instanceof Function))
continue;
length = (int) Context.toNumber(
ScriptableObject.getProperty(p, "length"));
} else if (f instanceof FunctionNode) {
length = ((FunctionNode) f).getVariableTable()
.getParameterCount();
} else {
continue;
}
Class[] parms = new Class[length];
for (int k=0; k < length; k++)
parms[k] = Object.class;
generateMethod(cfw, adapterName, id, parms, Object.class);
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream(512);
try {
cfw.write(out);
@ -285,8 +296,8 @@ public class JavaAdapter extends ScriptableObject {
* Utility method, which dynamically binds a Context to the current thread,
* if none already exists.
*/
public static Object callMethod(Scriptable object, String methodId,
Object[] args)
public static Object callMethod(Scriptable object, Object thisObj,
String methodId, Object[] args)
{
try {
Context cx = Context.enter();
@ -298,7 +309,7 @@ public class JavaAdapter extends ScriptableObject {
// the error.
fun = Undefined.instance;
}
return ScriptRuntime.call(cx, fun, object, args, object);
return ScriptRuntime.call(cx, fun, thisObj, args, object);
} catch (JavaScriptException ex) {
throw WrappedException.wrapException(ex);
} finally {
@ -328,23 +339,29 @@ public class JavaAdapter extends ScriptableObject {
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESPECIAL, superName, "<init>", "()", "V");
// Save parameter in instance variable "self"
// Save parameter in instance variable "delegee"
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.PUTFIELD, adapterName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
// create a wrapper object to be used as "this" in method calls
cfw.add(ByteCode.ALOAD_1); // the Scriptable
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESTATIC,
"org/mozilla/javascript/JavaAdapter",
"setAdapterProto",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/Object;)",
"Lorg/mozilla/javascript/Scriptable;");
// save the wrapper
cfw.add(ByteCode.ASTORE_1);
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
"Lorg/mozilla/javascript/Scriptable;");
// Set the prototype of the js object to be a LiveConnect
// wrapper of the generated class's object
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESTATIC,
"org/mozilla/javascript/ScriptRuntime",
"setAdapterProto",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/Object;)",
"V");
cfw.add(ByteCode.RETURN);
cfw.stopMethod((short)20, null); // TODO: magic number "20"
}
@ -371,22 +388,27 @@ public class JavaAdapter extends ScriptableObject {
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.ASTORE_1);
// Save the Scriptable in instance variable "self"
// Save the Scriptable in instance variable "delegee"
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // the Scriptable
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
cfw.add(ByteCode.PUTFIELD, adapterName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
// Set the prototype of the js object to be a LiveConnect
// wrapper of the generated class's object
// create a wrapper object to be used as "this" in method calls
cfw.add(ByteCode.ALOAD_1); // the Scriptable
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESTATIC,
"org/mozilla/javascript/ScriptRuntime",
"org/mozilla/javascript/JavaAdapter",
"setAdapterProto",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/Object;)",
"V");
"Lorg/mozilla/javascript/Scriptable;");
//save the wrapper
cfw.add(ByteCode.ASTORE_1);
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.RETURN);
cfw.stopMethod((short)20, null); // TODO: magic number "20"
@ -571,7 +593,7 @@ public class JavaAdapter extends ScriptableObject {
// load this.self into a local the first time it's needed.
// it will provide the scope needed by Context.toObject().
cfw.add(ByteCode.ALOAD_0);
cfw.add(ByteCode.GETFIELD, genName, "self",
cfw.add(ByteCode.GETFIELD, genName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.ASTORE, scopeLocal);
loadedScope = true;
@ -597,10 +619,12 @@ public class JavaAdapter extends ScriptableObject {
cfw.add(ByteCode.AASTORE);
}
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_0);
cfw.add(ByteCode.GETFIELD, genName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.ALOAD_0);
cfw.add(ByteCode.GETFIELD, genName, "self",
"Lorg/mozilla/javascript/Scriptable;");
cfw.addLoadConstant(methodName);
cfw.add(ByteCode.ALOAD, arrayLocal);
@ -610,7 +634,7 @@ public class JavaAdapter extends ScriptableObject {
"org/mozilla/javascript/JavaAdapter",
"callMethod",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/String;[Ljava/lang/Object;)",
"Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)",
"Ljava/lang/Object;");
if (returnType.equals(Void.TYPE)) {
@ -619,7 +643,7 @@ public class JavaAdapter extends ScriptableObject {
} else {
generateReturnResult(cfw, returnType);
}
cfw.stopMethod((short)(scopeLocal + 1), null);
cfw.stopMethod((short)(scopeLocal + 3), null);
}
/**
@ -800,51 +824,51 @@ public class JavaAdapter extends ScriptableObject {
}
}
/**
* Provides a key with which to distinguish previously generated
* adapter classes stored in a hash table.
*/
/**
* Provides a key with which to distinguish previously generated
* adapter classes stored in a hash table.
*/
static class ClassSignature {
Class mSuperClass;
Class[] mInterfaces;
Object[] mProperties;
Class mSuperClass;
Class[] mInterfaces;
Object[] mProperties; // JDK1.2: Use HashSet
ClassSignature(Class superClass, Class[] interfaces, Scriptable jsObj) {
mSuperClass = superClass;
mInterfaces = interfaces;
mProperties = jsObj.getIds();
}
public boolean equals(Object obj) {
if (obj instanceof ClassSignature) {
ClassSignature sig = (ClassSignature) obj;
if (mSuperClass == sig.mSuperClass) {
Class[] interfaces = sig.mInterfaces;
if (mInterfaces != interfaces) {
if (mInterfaces == null || interfaces == null)
return false;
if (mInterfaces.length != interfaces.length)
return false;
for (int i = 0; i < interfaces.length; i++)
if (mInterfaces[i] != interfaces[i])
return false;
}
Object[] properties = sig.mProperties;
if (mProperties.length != properties.length)
return false;
for (int i = 0; i < properties.length; i++)
if (!mProperties[i].equals(properties[i]))
return false;
return true;
}
}
return false;
}
public int hashCode() {
return mSuperClass.hashCode();
}
}
ClassSignature(Class superClass, Class[] interfaces, Scriptable jsObj) {
mSuperClass = superClass;
mInterfaces = interfaces;
mProperties = ScriptableObject.getPropertyIds(jsObj);
}
public boolean equals(Object obj) {
if (obj instanceof ClassSignature) {
ClassSignature sig = (ClassSignature) obj;
if (mSuperClass == sig.mSuperClass) {
Class[] interfaces = sig.mInterfaces;
if (mInterfaces != interfaces) {
if (mInterfaces == null || interfaces == null)
return false;
if (mInterfaces.length != interfaces.length)
return false;
for (int i=0; i < interfaces.length; i++)
if (mInterfaces[i] != interfaces[i])
return false;
}
if (mProperties.length != sig.mProperties.length)
return false;
for (int i=0; i < mProperties.length; i++) {
if (!mProperties[i].equals(sig.mProperties[i]))
return false;
}
return true;
}
}
return false;
}
public int hashCode() {
return mSuperClass.hashCode();
}
}
private static int serial;
private static MyClassLoader classLoader;

Просмотреть файл

@ -1909,14 +1909,6 @@ public class ScriptRuntime {
return global;
}
public static void setAdapterProto(Scriptable obj, Object adapter) {
Scriptable oldProto = obj.getPrototype();
Scriptable scope = ScriptableObject.getTopLevelScope(obj);
Scriptable wrapped = (Scriptable) Context.toObject(adapter, scope);
obj.setPrototype(wrapped);
wrapped.setPrototype(oldProto);
}
public static Scriptable initVarObj(Context cx, Scriptable scope,
NativeFunction funObj,
Scriptable thisObj, Object[] args)

Просмотреть файл

@ -1337,6 +1337,7 @@ public abstract class ScriptableObject implements Scriptable {
* @return the value of a property with name <code>name</code> found in
* <code>obj</code> or any object in its prototype chain, or
* <code>Scriptable.NOT_FOUND</code> if not found
* @since 1.5R2
*/
public static Object getProperty(Scriptable obj, String name) {
Scriptable start = obj;
@ -1363,6 +1364,7 @@ public abstract class ScriptableObject implements Scriptable {
* @return the value of a property with index <code>index</code> found in
* <code>obj</code> or any object in its prototype chain, or
* <code>Scriptable.NOT_FOUND</code> if not found
* @since 1.5R2
*/
public static Object getProperty(Scriptable obj, int index) {
Scriptable start = obj;
@ -1385,6 +1387,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param name a property name
* @param value any JavaScript value accepted by Scriptable.put
* @since 1.5R2
*/
public static void putProperty(Scriptable obj, String name, Object value) {
Scriptable base = getBase(obj, name);
@ -1402,6 +1405,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param index a property index
* @param value any JavaScript value accepted by Scriptable.put
* @since 1.5R2
*/
public static void putProperty(Scriptable obj, int index, Object value) {
Scriptable base = getBase(obj, index);
@ -1419,6 +1423,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param name a property name
* @return true if the property doesn't exist or was successfully removed
* @since 1.5R2
*/
public static boolean deleteProperty(Scriptable obj, String name) {
Scriptable base = getBase(obj, name);
@ -1437,6 +1442,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param index a property index
* @return true if the property doesn't exist or was successfully removed
* @since 1.5R2
*/
public static boolean deleteProperty(Scriptable obj, int index) {
Scriptable base = getBase(obj, index);
@ -1445,6 +1451,32 @@ public abstract class ScriptableObject implements Scriptable {
base.delete(index);
return base.get(index, obj) == NOT_FOUND;
}
/**
* Returns an array of all ids from an object and its prototypes.
* <p>
* @param obj a JavaScript object
* @return an array of all ids from all object in the prototype chain.
* If a given id occurs multiple times in the prototype chain,
* it will occur only once in this list.
* @since 1.5R2
*/
public static Object[] getPropertyIds(Scriptable obj) {
Hashtable h = new Hashtable(); // JDK1.2: use HashSet
while (obj != null) {
Object[] ids = obj.getIds();
for (int i=0; i < ids.length; i++) {
h.put(ids[i], ids[i]);
}
}
Object[] result = new Object[h.size()];
java.util.Enumeration e = h.elements();
int n = 0;
while (e.hasMoreElements()) {
result[n++] = e.nextElement();
}
return result;
}
private static Scriptable getBase(Scriptable obj, String s) {
Scriptable m = obj;

Просмотреть файл

@ -67,7 +67,13 @@ public class JavaAdapter extends ScriptableObject {
}
return NativeJavaObject.coerceType(c, result);
}
public static Scriptable setAdapterProto(Scriptable obj, Object adapter) {
Scriptable res = ScriptRuntime.toObject(ScriptableObject.getTopLevelScope(obj),adapter);
res.setPrototype(obj);
return res;
}
public static Object js_JavaAdapter(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
throws InstantiationException, NoSuchMethodException,
@ -107,7 +113,7 @@ public class JavaAdapter extends ScriptableObject {
Class[] ctorParms = { Scriptable.class };
Object[] ctorArgs = { obj };
Object v = adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
return cx.toObject(v, ScriptableObject.getTopLevelScope(ctorObj));
return setAdapterProto(obj,v);
}
public static Class createAdapterClass(Context cx, Scriptable jsObj,
@ -120,6 +126,9 @@ public class JavaAdapter extends ScriptableObject {
ClassFileWriter cfw = new ClassFileWriter(adapterName,
superClass.getName(),
"<adapter>");
cfw.addField("delegee", "Lorg/mozilla/javascript/Scriptable;",
(short) (ClassFileWriter.ACC_PUBLIC |
ClassFileWriter.ACC_FINAL));
cfw.addField("self", "Lorg/mozilla/javascript/Scriptable;",
(short) (ClassFileWriter.ACC_PUBLIC |
ClassFileWriter.ACC_FINAL));
@ -174,7 +183,7 @@ public class JavaAdapter extends ScriptableObject {
// has a property of the same name, then an override is intended.
boolean isAbstractMethod = Modifier.isAbstract(mods);
if (isAbstractMethod ||
(jsObj != null && jsObj.has(method.getName(), jsObj)))
(jsObj != null && ScriptableObject.getProperty(jsObj,method.getName()) != Scriptable.NOT_FOUND))
{
// make sure to generate only one instance of a particular
// method/signature.
@ -201,32 +210,34 @@ public class JavaAdapter extends ScriptableObject {
// Generate Java methods, fields for remaining properties that
// are not overrides.
Object[] ids = jsObj.getIds();
for (int j=0; j < ids.length; j++) {
if (!(ids[j] instanceof String))
continue;
String id = (String) ids[j];
if (generatedMethods.containsKey(id))
continue;
Object f = jsObj.get(id, jsObj);
int length;
if (f instanceof Scriptable) {
Scriptable p = (Scriptable) f;
if (!(p instanceof Function))
for (Scriptable o = jsObj; o != null; o = (Scriptable)o.getPrototype()) {
Object[] ids = jsObj.getIds();
for (int j=0; j < ids.length; j++) {
if (!(ids[j] instanceof String))
continue;
length = (int) Context.toNumber(
ScriptableObject.getProperty(p, "length"));
} else if (f instanceof FunctionNode) {
length = ((FunctionNode) f).getVariableTable().getParameterCount();
} else {
continue;
}
Class[] parms = new Class[length];
for (int k=0; k < length; k++)
parms[k] = Object.class;
generateMethod(cfw, adapterName, id, parms, Object.class);
}
String id = (String) ids[j];
if (generatedMethods.containsKey(id))
continue;
Object f = o.get(id, o);
int length;
if (f instanceof Scriptable) {
Scriptable p = (Scriptable) f;
if (!(p instanceof Function))
continue;
length = (int) Context.toNumber(
ScriptableObject.getProperty(p, "length"));
} else if (f instanceof FunctionNode) {
length = ((FunctionNode) f).getVariableTable()
.getParameterCount();
} else {
continue;
}
Class[] parms = new Class[length];
for (int k=0; k < length; k++)
parms[k] = Object.class;
generateMethod(cfw, adapterName, id, parms, Object.class);
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream(512);
try {
cfw.write(out);
@ -285,8 +296,8 @@ public class JavaAdapter extends ScriptableObject {
* Utility method, which dynamically binds a Context to the current thread,
* if none already exists.
*/
public static Object callMethod(Scriptable object, String methodId,
Object[] args)
public static Object callMethod(Scriptable object, Object thisObj,
String methodId, Object[] args)
{
try {
Context cx = Context.enter();
@ -298,7 +309,7 @@ public class JavaAdapter extends ScriptableObject {
// the error.
fun = Undefined.instance;
}
return ScriptRuntime.call(cx, fun, object, args, object);
return ScriptRuntime.call(cx, fun, thisObj, args, object);
} catch (JavaScriptException ex) {
throw WrappedException.wrapException(ex);
} finally {
@ -328,23 +339,29 @@ public class JavaAdapter extends ScriptableObject {
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESPECIAL, superName, "<init>", "()", "V");
// Save parameter in instance variable "self"
// Save parameter in instance variable "delegee"
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.PUTFIELD, adapterName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
// create a wrapper object to be used as "this" in method calls
cfw.add(ByteCode.ALOAD_1); // the Scriptable
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESTATIC,
"org/mozilla/javascript/JavaAdapter",
"setAdapterProto",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/Object;)",
"Lorg/mozilla/javascript/Scriptable;");
// save the wrapper
cfw.add(ByteCode.ASTORE_1);
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
"Lorg/mozilla/javascript/Scriptable;");
// Set the prototype of the js object to be a LiveConnect
// wrapper of the generated class's object
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESTATIC,
"org/mozilla/javascript/ScriptRuntime",
"setAdapterProto",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/Object;)",
"V");
cfw.add(ByteCode.RETURN);
cfw.stopMethod((short)20, null); // TODO: magic number "20"
}
@ -371,22 +388,27 @@ public class JavaAdapter extends ScriptableObject {
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.ASTORE_1);
// Save the Scriptable in instance variable "self"
// Save the Scriptable in instance variable "delegee"
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // the Scriptable
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
cfw.add(ByteCode.PUTFIELD, adapterName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
// Set the prototype of the js object to be a LiveConnect
// wrapper of the generated class's object
// create a wrapper object to be used as "this" in method calls
cfw.add(ByteCode.ALOAD_1); // the Scriptable
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.INVOKESTATIC,
"org/mozilla/javascript/ScriptRuntime",
"org/mozilla/javascript/JavaAdapter",
"setAdapterProto",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/Object;)",
"V");
"Lorg/mozilla/javascript/Scriptable;");
//save the wrapper
cfw.add(ByteCode.ASTORE_1);
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_1); // first arg
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.RETURN);
cfw.stopMethod((short)20, null); // TODO: magic number "20"
@ -571,7 +593,7 @@ public class JavaAdapter extends ScriptableObject {
// load this.self into a local the first time it's needed.
// it will provide the scope needed by Context.toObject().
cfw.add(ByteCode.ALOAD_0);
cfw.add(ByteCode.GETFIELD, genName, "self",
cfw.add(ByteCode.GETFIELD, genName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.ASTORE, scopeLocal);
loadedScope = true;
@ -597,10 +619,12 @@ public class JavaAdapter extends ScriptableObject {
cfw.add(ByteCode.AASTORE);
}
cfw.add(ByteCode.ALOAD_0); // this
cfw.add(ByteCode.ALOAD_0);
cfw.add(ByteCode.GETFIELD, genName, "delegee",
"Lorg/mozilla/javascript/Scriptable;");
cfw.add(ByteCode.ALOAD_0);
cfw.add(ByteCode.GETFIELD, genName, "self",
"Lorg/mozilla/javascript/Scriptable;");
cfw.addLoadConstant(methodName);
cfw.add(ByteCode.ALOAD, arrayLocal);
@ -610,7 +634,7 @@ public class JavaAdapter extends ScriptableObject {
"org/mozilla/javascript/JavaAdapter",
"callMethod",
"(Lorg/mozilla/javascript/Scriptable;" +
"Ljava/lang/String;[Ljava/lang/Object;)",
"Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)",
"Ljava/lang/Object;");
if (returnType.equals(Void.TYPE)) {
@ -619,7 +643,7 @@ public class JavaAdapter extends ScriptableObject {
} else {
generateReturnResult(cfw, returnType);
}
cfw.stopMethod((short)(scopeLocal + 1), null);
cfw.stopMethod((short)(scopeLocal + 3), null);
}
/**
@ -800,51 +824,51 @@ public class JavaAdapter extends ScriptableObject {
}
}
/**
* Provides a key with which to distinguish previously generated
* adapter classes stored in a hash table.
*/
/**
* Provides a key with which to distinguish previously generated
* adapter classes stored in a hash table.
*/
static class ClassSignature {
Class mSuperClass;
Class[] mInterfaces;
Object[] mProperties;
Class mSuperClass;
Class[] mInterfaces;
Object[] mProperties; // JDK1.2: Use HashSet
ClassSignature(Class superClass, Class[] interfaces, Scriptable jsObj) {
mSuperClass = superClass;
mInterfaces = interfaces;
mProperties = jsObj.getIds();
}
public boolean equals(Object obj) {
if (obj instanceof ClassSignature) {
ClassSignature sig = (ClassSignature) obj;
if (mSuperClass == sig.mSuperClass) {
Class[] interfaces = sig.mInterfaces;
if (mInterfaces != interfaces) {
if (mInterfaces == null || interfaces == null)
return false;
if (mInterfaces.length != interfaces.length)
return false;
for (int i = 0; i < interfaces.length; i++)
if (mInterfaces[i] != interfaces[i])
return false;
}
Object[] properties = sig.mProperties;
if (mProperties.length != properties.length)
return false;
for (int i = 0; i < properties.length; i++)
if (!mProperties[i].equals(properties[i]))
return false;
return true;
}
}
return false;
}
public int hashCode() {
return mSuperClass.hashCode();
}
}
ClassSignature(Class superClass, Class[] interfaces, Scriptable jsObj) {
mSuperClass = superClass;
mInterfaces = interfaces;
mProperties = ScriptableObject.getPropertyIds(jsObj);
}
public boolean equals(Object obj) {
if (obj instanceof ClassSignature) {
ClassSignature sig = (ClassSignature) obj;
if (mSuperClass == sig.mSuperClass) {
Class[] interfaces = sig.mInterfaces;
if (mInterfaces != interfaces) {
if (mInterfaces == null || interfaces == null)
return false;
if (mInterfaces.length != interfaces.length)
return false;
for (int i=0; i < interfaces.length; i++)
if (mInterfaces[i] != interfaces[i])
return false;
}
if (mProperties.length != sig.mProperties.length)
return false;
for (int i=0; i < mProperties.length; i++) {
if (!mProperties[i].equals(sig.mProperties[i]))
return false;
}
return true;
}
}
return false;
}
public int hashCode() {
return mSuperClass.hashCode();
}
}
private static int serial;
private static MyClassLoader classLoader;

Просмотреть файл

@ -1909,14 +1909,6 @@ public class ScriptRuntime {
return global;
}
public static void setAdapterProto(Scriptable obj, Object adapter) {
Scriptable oldProto = obj.getPrototype();
Scriptable scope = ScriptableObject.getTopLevelScope(obj);
Scriptable wrapped = (Scriptable) Context.toObject(adapter, scope);
obj.setPrototype(wrapped);
wrapped.setPrototype(oldProto);
}
public static Scriptable initVarObj(Context cx, Scriptable scope,
NativeFunction funObj,
Scriptable thisObj, Object[] args)

Просмотреть файл

@ -1337,6 +1337,7 @@ public abstract class ScriptableObject implements Scriptable {
* @return the value of a property with name <code>name</code> found in
* <code>obj</code> or any object in its prototype chain, or
* <code>Scriptable.NOT_FOUND</code> if not found
* @since 1.5R2
*/
public static Object getProperty(Scriptable obj, String name) {
Scriptable start = obj;
@ -1363,6 +1364,7 @@ public abstract class ScriptableObject implements Scriptable {
* @return the value of a property with index <code>index</code> found in
* <code>obj</code> or any object in its prototype chain, or
* <code>Scriptable.NOT_FOUND</code> if not found
* @since 1.5R2
*/
public static Object getProperty(Scriptable obj, int index) {
Scriptable start = obj;
@ -1385,6 +1387,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param name a property name
* @param value any JavaScript value accepted by Scriptable.put
* @since 1.5R2
*/
public static void putProperty(Scriptable obj, String name, Object value) {
Scriptable base = getBase(obj, name);
@ -1402,6 +1405,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param index a property index
* @param value any JavaScript value accepted by Scriptable.put
* @since 1.5R2
*/
public static void putProperty(Scriptable obj, int index, Object value) {
Scriptable base = getBase(obj, index);
@ -1419,6 +1423,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param name a property name
* @return true if the property doesn't exist or was successfully removed
* @since 1.5R2
*/
public static boolean deleteProperty(Scriptable obj, String name) {
Scriptable base = getBase(obj, name);
@ -1437,6 +1442,7 @@ public abstract class ScriptableObject implements Scriptable {
* @param obj a JavaScript object
* @param index a property index
* @return true if the property doesn't exist or was successfully removed
* @since 1.5R2
*/
public static boolean deleteProperty(Scriptable obj, int index) {
Scriptable base = getBase(obj, index);
@ -1445,6 +1451,32 @@ public abstract class ScriptableObject implements Scriptable {
base.delete(index);
return base.get(index, obj) == NOT_FOUND;
}
/**
* Returns an array of all ids from an object and its prototypes.
* <p>
* @param obj a JavaScript object
* @return an array of all ids from all object in the prototype chain.
* If a given id occurs multiple times in the prototype chain,
* it will occur only once in this list.
* @since 1.5R2
*/
public static Object[] getPropertyIds(Scriptable obj) {
Hashtable h = new Hashtable(); // JDK1.2: use HashSet
while (obj != null) {
Object[] ids = obj.getIds();
for (int i=0; i < ids.length; i++) {
h.put(ids[i], ids[i]);
}
}
Object[] result = new Object[h.size()];
java.util.Enumeration e = h.elements();
int n = 0;
while (e.hasMoreElements()) {
result[n++] = e.nextElement();
}
return result;
}
private static Scriptable getBase(Scriptable obj, String s) {
Scriptable m = obj;