diff --git a/js/rhino/examples/Control.java b/js/rhino/examples/Control.java index eefc62d874b..ebc7ecb92a2 100644 --- a/js/rhino/examples/Control.java +++ b/js/rhino/examples/Control.java @@ -72,36 +72,31 @@ public class Control { // ignore } - FlattenedObject global = new FlattenedObject(scope); - - FlattenedObject f = (FlattenedObject) global.getProperty("obj"); + Scriptable obj = (Scriptable) scope.get("obj", scope); // Should print "obj == result" (Since the result of an assignment // expression is the value that was assigned) - System.out.println("obj " + (f.getObject() == result ? "==" : "!=") + + System.out.println("obj " + (obj == result ? "==" : "!=") + " result"); - // Should print "f.a == 1" - System.out.println("f.a == " + f.getProperty("a")); + // Should print "obj.a == 1" + System.out.println("obj.a == " + obj.get("a", obj)); - FlattenedObject b = (FlattenedObject) f.getProperty("b"); + Scriptable b = (Scriptable) obj.get("b", obj); - // Should print "f.b[0] == x" - System.out.println("f.b[0] == " + b.getProperty(new Integer(0))); + // Should print "obj.b[0] == x" + System.out.println("obj.b[0] == " + b.get(0, b)); - // Should print "f.b[1] == y" - System.out.println("f.b[1] == " + b.getProperty(new Integer(1))); + // Should print "obj.b[1] == y" + System.out.println("obj.b[1] == " + b.get(1, b)); try { // Should print {a:1, b:["x", "y"]} - System.out.println(f.callMethod("toString", new Object[0])); - } catch (PropertyException e) { - // ignore - } catch (NotAFunctionException e) { - // ignore + Function fn = (Function) ScriptableObject.getProperty(obj, "toString"); + System.out.println(fn.call(cx, scope, obj, new Object[0])); } catch (JavaScriptException e) { // ignore - } + } cx.exit(); } diff --git a/js/rhino/org/mozilla/javascript/ClassOutput.java b/js/rhino/org/mozilla/javascript/ClassOutput.java index 1474da17aab..31fa520b231 100644 --- a/js/rhino/org/mozilla/javascript/ClassOutput.java +++ b/js/rhino/org/mozilla/javascript/ClassOutput.java @@ -34,7 +34,7 @@ */ package org.mozilla.javascript; -// API Class +// API class import java.io.*; diff --git a/js/rhino/org/mozilla/javascript/FlattenedObject.java b/js/rhino/org/mozilla/javascript/FlattenedObject.java index c345c6fa408..950f0c9ae9a 100644 --- a/js/rhino/org/mozilla/javascript/FlattenedObject.java +++ b/js/rhino/org/mozilla/javascript/FlattenedObject.java @@ -34,8 +34,6 @@ * file under either the NPL or the GPL. */ -// API class - package org.mozilla.javascript; import java.util.Hashtable; @@ -44,19 +42,13 @@ import java.util.Enumeration; /** * Manipulate a Scriptable object as if its prototype chain were flattened. *
- * Compared to the Scriptable interface, FlattenedObject provides a view of - * Scriptable objects that is easier to use and more closely matches a script - * writer's view of a JavaScript object.
+ * This class has been deprecated in favor of the static methods
+ * getProperty
, putProperty
, and
+ * deleteProperty
. Those methods provide the
+ * same functionality without the confusing and inefficient need to construct
+ * a new object instance.
*
- * A FlattenedObject is "flattened" in the sense that multiple objects in a
- * prototype chain appear to have their properties all appear in the
- * FlattenedObject.
- * - * Another convenience provided by Flattened object is the ability to access - * properties by a single java.lang.Object id. This id is then converted into - * a String or an int before methods of the Scriptable object are called. - * - * @see org.mozilla.javascript.Scriptable + * @see org.mozilla.javascript.ScriptableObject * * @author Norris Boyd */ @@ -67,6 +59,7 @@ public class FlattenedObject { * Construct a new FlattenedObject. * * @param object the object to be viewed with flattened properties + * @deprecated */ public FlattenedObject(Scriptable object) { this.obj = object; @@ -74,6 +67,7 @@ public class FlattenedObject { /** * Get the associated Scriptable object. + * @deprecated */ public Scriptable getObject() { return obj; @@ -93,6 +87,7 @@ public class FlattenedObject { * @return true if and only if the property exists in the prototype * chain * @see org.mozilla.javascript.Scriptable#has + * @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty */ public boolean hasProperty(Object id) { String stringId = ScriptRuntime.toString(id); @@ -119,6 +114,7 @@ public class FlattenedObject { * @return the value of the property or the undefined value * @see org.mozilla.javascript.Scriptable#get * @see org.mozilla.javascript.Context#getUndefinedValue + * @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty */ public Object getProperty(Object id) { String s = ScriptRuntime.getStringId(id); @@ -149,6 +145,7 @@ public class FlattenedObject { * a Number * @param value the value of the property * @see org.mozilla.javascript.Scriptable#put + * @deprecated As of 1.5R2, replaced by ScriptableObject.putProperty */ public void putProperty(Object id, Object value) { String s = ScriptRuntime.getStringId(id); @@ -179,6 +176,7 @@ public class FlattenedObject { * a Number * @return true if the property didn't exist, or existed and was removed * @see org.mozilla.javascript.Scriptable#delete + * @deprecated as of 1.5R2, replaced by ScriptableObject.deleteProperty */ public boolean deleteProperty(Object id) { String s = ScriptRuntime.getStringId(id); @@ -208,6 +206,7 @@ public class FlattenedObject { * array will be unique respective to equals().) * * @see org.mozilla.javascript.Scriptable#getIds + * @deprecated */ public Object[] getIds() { Hashtable h = new Hashtable(11); @@ -241,6 +240,7 @@ public class FlattenedObject { * @exception JavaScriptException if an uncaught JavaScript exception * occurred while executing the function * @see org.mozilla.javascript.Function#call + * @deprecated */ public Object call(Context cx, Scriptable thisObj, Object[] args) throws NotAFunctionException, @@ -263,6 +263,7 @@ public class FlattenedObject { * @exception JavaScriptException if an uncaught JavaScript exception * occurred while executing the constructor * @see org.mozilla.javascript.Function#construct + * @deprecated */ public Scriptable construct(Context cx, Object[] args) throws NotAFunctionException, @@ -297,6 +298,7 @@ public class FlattenedObject { * @exception JavaScriptException if an uncaught JavaScript exception * occurred while executing the method * @see org.mozilla.javascript.Function#call + * @deprecated */ public Object callMethod(Object id, Object[] args) throws PropertyException, diff --git a/js/rhino/org/mozilla/javascript/JavaAdapter.java b/js/rhino/org/mozilla/javascript/JavaAdapter.java index 7c5c559e235..848e3c2b7be 100644 --- a/js/rhino/org/mozilla/javascript/JavaAdapter.java +++ b/js/rhino/org/mozilla/javascript/JavaAdapter.java @@ -214,7 +214,8 @@ public class JavaAdapter extends ScriptableObject { Scriptable p = (Scriptable) f; if (!(p instanceof Function)) continue; - length = (int) Context.toNumber(getProperty(p, "length")); + length = (int) Context.toNumber( + ScriptableObject.getProperty(p, "length")); } else if (f instanceof FunctionNode) { length = ((FunctionNode) f).getVariableTable().getParameterCount(); } else { @@ -771,24 +772,6 @@ public class JavaAdapter extends ScriptableObject { return sb; } - /** - * Looks up a property of a scriptable object, searching the entire prototype - * chain. Works like FlattenedObject.getProperty() without the overhead. - */ - private static Object getProperty(Scriptable obj, String id) { - Scriptable m = obj; - Object result = null; - for(;;) { - result = m.get(id, obj); - if (result != Scriptable.NOT_FOUND) - break; - m = m.getPrototype(); - if (m == null) - return Undefined.instance; - } - return result; - } - static final class MyClassLoader extends ClassLoader { public Class defineClass(String name, byte data[]) { return super.defineClass(name, data, 0, data.length); diff --git a/js/rhino/org/mozilla/javascript/NativeFunction.java b/js/rhino/org/mozilla/javascript/NativeFunction.java index e2a9e300976..e2fc45ed071 100644 --- a/js/rhino/org/mozilla/javascript/NativeFunction.java +++ b/js/rhino/org/mozilla/javascript/NativeFunction.java @@ -115,13 +115,9 @@ public class NativeFunction extends ScriptableObject implements Function { * */ public boolean hasInstance(Scriptable instance) { - FlattenedObject flat = new FlattenedObject(this); - Object protoProp = flat.getProperty("prototype"); - if (protoProp instanceof FlattenedObject) { - protoProp = ((FlattenedObject)protoProp).getObject(); - if (protoProp != Undefined.instance) - return ScriptRuntime.jsDelegatesTo(instance, - (Scriptable)protoProp); + Object protoProp = ScriptableObject.getProperty(this, "prototype"); + if (protoProp instanceof Scriptable && protoProp != Undefined.instance) { + return ScriptRuntime.jsDelegatesTo(instance, (Scriptable)protoProp); } Object[] args = { names[0] }; String m = ScriptRuntime.getMessage("msg.instanceof.bad.prototype", diff --git a/js/rhino/org/mozilla/javascript/NativeJavaObject.java b/js/rhino/org/mozilla/javascript/NativeJavaObject.java index 4fc3fbe0107..226900183f3 100644 --- a/js/rhino/org/mozilla/javascript/NativeJavaObject.java +++ b/js/rhino/org/mozilla/javascript/NativeJavaObject.java @@ -183,8 +183,6 @@ public class NativeJavaObject implements Scriptable, Wrapper { // Just abandon conversion from JSObject } } - if (cls == ScriptRuntime.ClassClass) - return NativeJavaClass.wrap(scope, (Class) obj); return new NativeJavaObject(scope, obj, staticType); } diff --git a/js/rhino/org/mozilla/javascript/ScriptRuntime.java b/js/rhino/org/mozilla/javascript/ScriptRuntime.java index 9911f87194d..b1b4e30f106 100644 --- a/js/rhino/org/mozilla/javascript/ScriptRuntime.java +++ b/js/rhino/org/mozilla/javascript/ScriptRuntime.java @@ -1059,10 +1059,11 @@ public class ScriptRuntime { * method doesn't return a value. */ public static Object delete(Object obj, Object id) { - if (!(obj instanceof Scriptable)) - return Boolean.TRUE; - FlattenedObject f = new FlattenedObject((Scriptable) obj); - return f.deleteProperty(id) ? Boolean.TRUE : Boolean.FALSE; + String s = getStringId(id); + boolean result = s != null + ? ScriptableObject.deleteProperty((Scriptable) obj, s) + : ScriptableObject.deleteProperty((Scriptable) obj, getIntId(id)); + return result ? Boolean.TRUE : Boolean.FALSE; } /** @@ -1730,9 +1731,11 @@ public class ScriptRuntime { Context.getContext(), "TypeError", ScriptRuntime.getMessage("msg.instanceof.not.object", null), a); } - // OPT do it here rather than making a new FlattenedObject. - FlattenedObject rhs = new FlattenedObject((Scriptable)b); - return rhs.hasProperty(a); + String s = getStringId(a); + Object result = s != null + ? ScriptableObject.getProperty((Scriptable) b, s) + : ScriptableObject.getProperty((Scriptable) b, getIntId(a)); + return result != Scriptable.NOT_FOUND; } public static Boolean cmp_LTB(Object val1, Object val2) { diff --git a/js/rhino/org/mozilla/javascript/Scriptable.java b/js/rhino/org/mozilla/javascript/Scriptable.java index 8dead5ff30d..ff53fb088ee 100644 --- a/js/rhino/org/mozilla/javascript/Scriptable.java +++ b/js/rhino/org/mozilla/javascript/Scriptable.java @@ -45,12 +45,12 @@ package org.mozilla.javascript; * Host system implementors may find it easier to extend the ScriptableObject * class rather than implementing Scriptable when writing host objects. *
- * There are many convenience methods defined in FlattenedObject that make - * accessing objects easier. + * There are many static methods defined in ScriptableObject that perform + * the multiple calls to the Scriptable interface needed in order to + * manipulate properties in prototype chains. *
*
* @see org.mozilla.javascript.ScriptableObject
- * @see org.mozilla.javascript.FlattenedObject
* @author Norris Boyd
* @author Nick Thompson
* @author Brendan Eich
@@ -137,7 +137,7 @@ public interface Scriptable {
* @param start the object in which the lookup began
* @return true if and only if the named property is found in the object
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#hasProperty
+ * @see org.mozilla.javascript.ScriptableObject#getProperty
*/
public boolean has(String name, Scriptable start);
@@ -153,7 +153,7 @@ public interface Scriptable {
* @param start the object in which the lookup began
* @return true if and only if the indexed property is found in the object
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#hasProperty
+ * @see org.mozilla.javascript.ScriptableObject#getProperty
*/
public boolean has(int index, Scriptable start);
@@ -167,8 +167,8 @@ public interface Scriptable {
* get
. A class that implements this method may choose
* to ignore calls to set certain properties, in which case those
* properties are effectively read-only.
- * For a more convenient (and less efficient) form of this method,
- * see putProperty
in FlattenedObject.
+ * For properties defined in a prototype chain,
+ * use putProperty
in ScriptableObject.
* Note that if a property a is defined in the prototype p
* of an object o, then evaluating o.a = 23
will cause
* set
to be called on the prototype p with
@@ -198,7 +198,7 @@ public interface Scriptable {
* @param value value to set the property to
* @see org.mozilla.javascript.Scriptable#has
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#putProperty
+ * @see org.mozilla.javascript.ScriptableObject#putProperty
*/
public void put(String name, Scriptable start, Object value);
@@ -217,7 +217,7 @@ public interface Scriptable {
* @see org.mozilla.javascript.Scriptable#has
* @see org.mozilla.javascript.Scriptable#get
* @see org.mozilla.javascript.Scriptable#put(String,Scriptable,Object)
- * @see org.mozilla.javascript.FlattenedObject#putProperty
+ * @see org.mozilla.javascript.ScriptaleObject#putProperty
*/
public void put(int index, Scriptable start, Object value);
@@ -235,11 +235,11 @@ public interface Scriptable {
* The property is specified by a String name
* as defined for get
.
*
- * For a more convenient form of this method,
- * see deleteProperty in FlattenedObject.
+ * To delete properties defined in a prototype chain,
+ * see deleteProperty in ScriptableObject.
* @param name the identifier for the property
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#deleteProperty
+ * @see org.mozilla.javascript.ScriptableObject#deleteProperty
*/
public void delete(String name);
@@ -249,15 +249,15 @@ public interface Scriptable {
* The property is specified by an integral index
* as defined for get
.
*
- * For a more convenient form of this method,
- * see deleteProperty in FlattenedObject.
+ * To delete properties defined in a prototype chain,
+ * see deleteProperty in ScriptableObject.
*
* Identical to delete(String)
except that
* an integral index is used to select the property.
*
* @param index the numeric index for the property
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#deleteProperty
+ * @see org.mozilla.javascript.ScriptableObject#deleteProperty
*/
public void delete(int index);
diff --git a/js/rhino/org/mozilla/javascript/ScriptableObject.java b/js/rhino/org/mozilla/javascript/ScriptableObject.java
index 25863d378f5..0166aadef46 100644
--- a/js/rhino/org/mozilla/javascript/ScriptableObject.java
+++ b/js/rhino/org/mozilla/javascript/ScriptableObject.java
@@ -524,17 +524,17 @@ public abstract class ScriptableObject implements Scriptable {
*/
public Object getDefaultValue(Class typeHint) {
Object val;
- FlattenedObject f = new FlattenedObject(this);
Context cx = null;
try {
for (int i=0; i < 2; i++) {
if (typeHint == ScriptRuntime.StringClass ? i == 0 : i == 1) {
- Function fun = getFunctionProperty(f, "toString");
- if (fun == null)
+ Object v = getProperty(this, "toString");
+ if (!(v instanceof Function))
continue;
+ Function fun = (Function) v;
if (cx == null)
cx = Context.getContext();
- val = fun.call(cx, fun.getParentScope(), f.getObject(),
+ val = fun.call(cx, fun.getParentScope(), this,
ScriptRuntime.emptyArgs);
} else {
String hint;
@@ -566,14 +566,14 @@ public abstract class ScriptableObject implements Scriptable {
throw Context.reportRuntimeError(
Context.getMessage("msg.invalid.type", args));
}
- Function fun = getFunctionProperty(f, "valueOf");
- if (fun == null)
+ Object v = getProperty(this, "valueOf");
+ if (!(v instanceof Function))
continue;
+ Function fun = (Function) v;
Object[] args = { hint };
if (cx == null)
cx = Context.getContext();
- val = fun.call(cx, fun.getParentScope(), f.getObject(),
- args);
+ val = fun.call(cx, fun.getParentScope(), this, args);
}
if (val != null && (val == Undefined.instance ||
!(val instanceof Scriptable) ||
@@ -1326,7 +1326,146 @@ public abstract class ScriptableObject implements Scriptable {
public boolean isSealed() {
return count == -1;
}
-
+
+ /**
+ * Gets a named property from an object or any object in its prototype chain.
+ *
+ * Searches the prototype chain for a property named name
.
+ *
+ * @param obj a JavaScript object
+ * @param name a property name
+ * @return the value of a property with name name
found in
+ * obj
or any object in its prototype chain, or
+ * Scriptable.NOT_FOUND
if not found
+ */
+ public static Object getProperty(Scriptable obj, String name) {
+ Scriptable start = obj;
+ Object result;
+ do {
+ result = obj.get(name, start);
+ if (result != Scriptable.NOT_FOUND)
+ break;
+ obj = obj.getPrototype();
+ } while (obj != null);
+ return result;
+ }
+
+ /**
+ * Gets an indexed property from an object or any object in its prototype chain.
+ *
+ * Searches the prototype chain for a property with integral index
+ * index
. Note that if you wish to look for properties with numerical
+ * but non-integral indicies, you should use getProperty(Scriptable,String) with
+ * the string value of the index.
+ *
+ * @param obj a JavaScript object
+ * @param index an integral index
+ * @return the value of a property with index index
found in
+ * obj
or any object in its prototype chain, or
+ * Scriptable.NOT_FOUND
if not found
+ */
+ public static Object getProperty(Scriptable obj, int index) {
+ Scriptable start = obj;
+ Object result;
+ do {
+ result = obj.get(index, start);
+ if (result != Scriptable.NOT_FOUND)
+ break;
+ obj = obj.getPrototype();
+ } while (obj != null);
+ return result;
+ }
+
+ /**
+ * Puts a named property in an object or in an object in its prototype chain.
+ *
+ * Seaches for the named property in the prototype chain. If it is found,
+ * the value of the property is changed. If it is not found, a new
+ * property is added in obj
.
+ * @param obj a JavaScript object
+ * @param name a property name
+ * @param value any JavaScript value accepted by Scriptable.put
+ */
+ public static void putProperty(Scriptable obj, String name, Object value) {
+ Scriptable base = getBase(obj, name);
+ if (base == null)
+ base = obj;
+ base.put(name, obj, value);
+ }
+
+ /**
+ * Puts an indexed property in an object or in an object in its prototype chain.
+ *
+ * Seaches for the indexed property in the prototype chain. If it is found,
+ * the value of the property is changed. If it is not found, a new
+ * property is added in obj
.
+ * @param obj a JavaScript object
+ * @param index a property index
+ * @param value any JavaScript value accepted by Scriptable.put
+ */
+ public static void putProperty(Scriptable obj, int index, Object value) {
+ Scriptable base = getBase(obj, index);
+ if (base == null)
+ base = obj;
+ base.put(index, obj, value);
+ }
+
+ /**
+ * Removes the property from an object or its prototype chain.
+ *
+ * Searches for a property with name
in obj or
+ * its prototype chain. If it is found, the object's delete
+ * method is called.
+ * @param obj a JavaScript object
+ * @param name a property name
+ * @return true if the property doesn't exist or was successfully removed
+ */
+ public static boolean deleteProperty(Scriptable obj, String name) {
+ Scriptable base = getBase(obj, name);
+ if (base == null)
+ return true;
+ base.delete(name);
+ return base.get(name, obj) == NOT_FOUND;
+ }
+
+ /**
+ * Removes the property from an object or its prototype chain.
+ *
+ * Searches for a property with index
in obj or
+ * its prototype chain. If it is found, the object's delete
+ * method is called.
+ * @param obj a JavaScript object
+ * @param index a property index
+ * @return true if the property doesn't exist or was successfully removed
+ */
+ public static boolean deleteProperty(Scriptable obj, int index) {
+ Scriptable base = getBase(obj, index);
+ if (base == null)
+ return true;
+ base.delete(index);
+ return base.get(index, obj) == NOT_FOUND;
+ }
+
+ private static Scriptable getBase(Scriptable obj, String s) {
+ Scriptable m = obj;
+ while (m != null) {
+ if (m.has(s, obj))
+ return m;
+ m = m.getPrototype();
+ }
+ return null;
+ }
+
+ private static Scriptable getBase(Scriptable obj, int index) {
+ Scriptable m = obj;
+ while (m != null) {
+ if (m.has(index, obj))
+ return m;
+ m = m.getPrototype();
+ }
+ return null;
+ }
+
/**
* Adds a property attribute to all properties.
*/
@@ -1476,16 +1615,6 @@ public abstract class ScriptableObject implements Scriptable {
slots = newSlots;
}
- private Function getFunctionProperty(FlattenedObject f, String name) {
- Object val = f.getProperty(name);
- if (val == null || !(val instanceof FlattenedObject))
- return null;
- Scriptable s = ((FlattenedObject) val).getObject();
- if (s instanceof Function)
- return (Function) s;
- return null;
- }
-
private static Hashtable getExclusionList() {
if (exclusionList != null)
return exclusionList;
diff --git a/js/rhino/src/org/mozilla/javascript/ClassOutput.java b/js/rhino/src/org/mozilla/javascript/ClassOutput.java
index 1474da17aab..31fa520b231 100644
--- a/js/rhino/src/org/mozilla/javascript/ClassOutput.java
+++ b/js/rhino/src/org/mozilla/javascript/ClassOutput.java
@@ -34,7 +34,7 @@
*/
package org.mozilla.javascript;
-// API Class
+// API class
import java.io.*;
diff --git a/js/rhino/src/org/mozilla/javascript/FlattenedObject.java b/js/rhino/src/org/mozilla/javascript/FlattenedObject.java
index c345c6fa408..950f0c9ae9a 100644
--- a/js/rhino/src/org/mozilla/javascript/FlattenedObject.java
+++ b/js/rhino/src/org/mozilla/javascript/FlattenedObject.java
@@ -34,8 +34,6 @@
* file under either the NPL or the GPL.
*/
-// API class
-
package org.mozilla.javascript;
import java.util.Hashtable;
@@ -44,19 +42,13 @@ import java.util.Enumeration;
/**
* Manipulate a Scriptable object as if its prototype chain were flattened.
*
- * Compared to the Scriptable interface, FlattenedObject provides a view of - * Scriptable objects that is easier to use and more closely matches a script - * writer's view of a JavaScript object.
+ * This class has been deprecated in favor of the static methods
+ * getProperty
, putProperty
, and
+ * deleteProperty
. Those methods provide the
+ * same functionality without the confusing and inefficient need to construct
+ * a new object instance.
*
- * A FlattenedObject is "flattened" in the sense that multiple objects in a
- * prototype chain appear to have their properties all appear in the
- * FlattenedObject.
- * - * Another convenience provided by Flattened object is the ability to access - * properties by a single java.lang.Object id. This id is then converted into - * a String or an int before methods of the Scriptable object are called. - * - * @see org.mozilla.javascript.Scriptable + * @see org.mozilla.javascript.ScriptableObject * * @author Norris Boyd */ @@ -67,6 +59,7 @@ public class FlattenedObject { * Construct a new FlattenedObject. * * @param object the object to be viewed with flattened properties + * @deprecated */ public FlattenedObject(Scriptable object) { this.obj = object; @@ -74,6 +67,7 @@ public class FlattenedObject { /** * Get the associated Scriptable object. + * @deprecated */ public Scriptable getObject() { return obj; @@ -93,6 +87,7 @@ public class FlattenedObject { * @return true if and only if the property exists in the prototype * chain * @see org.mozilla.javascript.Scriptable#has + * @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty */ public boolean hasProperty(Object id) { String stringId = ScriptRuntime.toString(id); @@ -119,6 +114,7 @@ public class FlattenedObject { * @return the value of the property or the undefined value * @see org.mozilla.javascript.Scriptable#get * @see org.mozilla.javascript.Context#getUndefinedValue + * @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty */ public Object getProperty(Object id) { String s = ScriptRuntime.getStringId(id); @@ -149,6 +145,7 @@ public class FlattenedObject { * a Number * @param value the value of the property * @see org.mozilla.javascript.Scriptable#put + * @deprecated As of 1.5R2, replaced by ScriptableObject.putProperty */ public void putProperty(Object id, Object value) { String s = ScriptRuntime.getStringId(id); @@ -179,6 +176,7 @@ public class FlattenedObject { * a Number * @return true if the property didn't exist, or existed and was removed * @see org.mozilla.javascript.Scriptable#delete + * @deprecated as of 1.5R2, replaced by ScriptableObject.deleteProperty */ public boolean deleteProperty(Object id) { String s = ScriptRuntime.getStringId(id); @@ -208,6 +206,7 @@ public class FlattenedObject { * array will be unique respective to equals().) * * @see org.mozilla.javascript.Scriptable#getIds + * @deprecated */ public Object[] getIds() { Hashtable h = new Hashtable(11); @@ -241,6 +240,7 @@ public class FlattenedObject { * @exception JavaScriptException if an uncaught JavaScript exception * occurred while executing the function * @see org.mozilla.javascript.Function#call + * @deprecated */ public Object call(Context cx, Scriptable thisObj, Object[] args) throws NotAFunctionException, @@ -263,6 +263,7 @@ public class FlattenedObject { * @exception JavaScriptException if an uncaught JavaScript exception * occurred while executing the constructor * @see org.mozilla.javascript.Function#construct + * @deprecated */ public Scriptable construct(Context cx, Object[] args) throws NotAFunctionException, @@ -297,6 +298,7 @@ public class FlattenedObject { * @exception JavaScriptException if an uncaught JavaScript exception * occurred while executing the method * @see org.mozilla.javascript.Function#call + * @deprecated */ public Object callMethod(Object id, Object[] args) throws PropertyException, diff --git a/js/rhino/src/org/mozilla/javascript/JavaAdapter.java b/js/rhino/src/org/mozilla/javascript/JavaAdapter.java index 7c5c559e235..848e3c2b7be 100644 --- a/js/rhino/src/org/mozilla/javascript/JavaAdapter.java +++ b/js/rhino/src/org/mozilla/javascript/JavaAdapter.java @@ -214,7 +214,8 @@ public class JavaAdapter extends ScriptableObject { Scriptable p = (Scriptable) f; if (!(p instanceof Function)) continue; - length = (int) Context.toNumber(getProperty(p, "length")); + length = (int) Context.toNumber( + ScriptableObject.getProperty(p, "length")); } else if (f instanceof FunctionNode) { length = ((FunctionNode) f).getVariableTable().getParameterCount(); } else { @@ -771,24 +772,6 @@ public class JavaAdapter extends ScriptableObject { return sb; } - /** - * Looks up a property of a scriptable object, searching the entire prototype - * chain. Works like FlattenedObject.getProperty() without the overhead. - */ - private static Object getProperty(Scriptable obj, String id) { - Scriptable m = obj; - Object result = null; - for(;;) { - result = m.get(id, obj); - if (result != Scriptable.NOT_FOUND) - break; - m = m.getPrototype(); - if (m == null) - return Undefined.instance; - } - return result; - } - static final class MyClassLoader extends ClassLoader { public Class defineClass(String name, byte data[]) { return super.defineClass(name, data, 0, data.length); diff --git a/js/rhino/src/org/mozilla/javascript/NativeFunction.java b/js/rhino/src/org/mozilla/javascript/NativeFunction.java index e2a9e300976..e2fc45ed071 100644 --- a/js/rhino/src/org/mozilla/javascript/NativeFunction.java +++ b/js/rhino/src/org/mozilla/javascript/NativeFunction.java @@ -115,13 +115,9 @@ public class NativeFunction extends ScriptableObject implements Function { * */ public boolean hasInstance(Scriptable instance) { - FlattenedObject flat = new FlattenedObject(this); - Object protoProp = flat.getProperty("prototype"); - if (protoProp instanceof FlattenedObject) { - protoProp = ((FlattenedObject)protoProp).getObject(); - if (protoProp != Undefined.instance) - return ScriptRuntime.jsDelegatesTo(instance, - (Scriptable)protoProp); + Object protoProp = ScriptableObject.getProperty(this, "prototype"); + if (protoProp instanceof Scriptable && protoProp != Undefined.instance) { + return ScriptRuntime.jsDelegatesTo(instance, (Scriptable)protoProp); } Object[] args = { names[0] }; String m = ScriptRuntime.getMessage("msg.instanceof.bad.prototype", diff --git a/js/rhino/src/org/mozilla/javascript/NativeJavaObject.java b/js/rhino/src/org/mozilla/javascript/NativeJavaObject.java index 4fc3fbe0107..226900183f3 100644 --- a/js/rhino/src/org/mozilla/javascript/NativeJavaObject.java +++ b/js/rhino/src/org/mozilla/javascript/NativeJavaObject.java @@ -183,8 +183,6 @@ public class NativeJavaObject implements Scriptable, Wrapper { // Just abandon conversion from JSObject } } - if (cls == ScriptRuntime.ClassClass) - return NativeJavaClass.wrap(scope, (Class) obj); return new NativeJavaObject(scope, obj, staticType); } diff --git a/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java b/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java index 9911f87194d..b1b4e30f106 100644 --- a/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java +++ b/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java @@ -1059,10 +1059,11 @@ public class ScriptRuntime { * method doesn't return a value. */ public static Object delete(Object obj, Object id) { - if (!(obj instanceof Scriptable)) - return Boolean.TRUE; - FlattenedObject f = new FlattenedObject((Scriptable) obj); - return f.deleteProperty(id) ? Boolean.TRUE : Boolean.FALSE; + String s = getStringId(id); + boolean result = s != null + ? ScriptableObject.deleteProperty((Scriptable) obj, s) + : ScriptableObject.deleteProperty((Scriptable) obj, getIntId(id)); + return result ? Boolean.TRUE : Boolean.FALSE; } /** @@ -1730,9 +1731,11 @@ public class ScriptRuntime { Context.getContext(), "TypeError", ScriptRuntime.getMessage("msg.instanceof.not.object", null), a); } - // OPT do it here rather than making a new FlattenedObject. - FlattenedObject rhs = new FlattenedObject((Scriptable)b); - return rhs.hasProperty(a); + String s = getStringId(a); + Object result = s != null + ? ScriptableObject.getProperty((Scriptable) b, s) + : ScriptableObject.getProperty((Scriptable) b, getIntId(a)); + return result != Scriptable.NOT_FOUND; } public static Boolean cmp_LTB(Object val1, Object val2) { diff --git a/js/rhino/src/org/mozilla/javascript/Scriptable.java b/js/rhino/src/org/mozilla/javascript/Scriptable.java index 8dead5ff30d..ff53fb088ee 100644 --- a/js/rhino/src/org/mozilla/javascript/Scriptable.java +++ b/js/rhino/src/org/mozilla/javascript/Scriptable.java @@ -45,12 +45,12 @@ package org.mozilla.javascript; * Host system implementors may find it easier to extend the ScriptableObject * class rather than implementing Scriptable when writing host objects. *
- * There are many convenience methods defined in FlattenedObject that make - * accessing objects easier. + * There are many static methods defined in ScriptableObject that perform + * the multiple calls to the Scriptable interface needed in order to + * manipulate properties in prototype chains. *
*
* @see org.mozilla.javascript.ScriptableObject
- * @see org.mozilla.javascript.FlattenedObject
* @author Norris Boyd
* @author Nick Thompson
* @author Brendan Eich
@@ -137,7 +137,7 @@ public interface Scriptable {
* @param start the object in which the lookup began
* @return true if and only if the named property is found in the object
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#hasProperty
+ * @see org.mozilla.javascript.ScriptableObject#getProperty
*/
public boolean has(String name, Scriptable start);
@@ -153,7 +153,7 @@ public interface Scriptable {
* @param start the object in which the lookup began
* @return true if and only if the indexed property is found in the object
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#hasProperty
+ * @see org.mozilla.javascript.ScriptableObject#getProperty
*/
public boolean has(int index, Scriptable start);
@@ -167,8 +167,8 @@ public interface Scriptable {
* get
. A class that implements this method may choose
* to ignore calls to set certain properties, in which case those
* properties are effectively read-only.
- * For a more convenient (and less efficient) form of this method,
- * see putProperty
in FlattenedObject.
+ * For properties defined in a prototype chain,
+ * use putProperty
in ScriptableObject.
* Note that if a property a is defined in the prototype p
* of an object o, then evaluating o.a = 23
will cause
* set
to be called on the prototype p with
@@ -198,7 +198,7 @@ public interface Scriptable {
* @param value value to set the property to
* @see org.mozilla.javascript.Scriptable#has
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#putProperty
+ * @see org.mozilla.javascript.ScriptableObject#putProperty
*/
public void put(String name, Scriptable start, Object value);
@@ -217,7 +217,7 @@ public interface Scriptable {
* @see org.mozilla.javascript.Scriptable#has
* @see org.mozilla.javascript.Scriptable#get
* @see org.mozilla.javascript.Scriptable#put(String,Scriptable,Object)
- * @see org.mozilla.javascript.FlattenedObject#putProperty
+ * @see org.mozilla.javascript.ScriptaleObject#putProperty
*/
public void put(int index, Scriptable start, Object value);
@@ -235,11 +235,11 @@ public interface Scriptable {
* The property is specified by a String name
* as defined for get
.
*
- * For a more convenient form of this method,
- * see deleteProperty in FlattenedObject.
+ * To delete properties defined in a prototype chain,
+ * see deleteProperty in ScriptableObject.
* @param name the identifier for the property
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#deleteProperty
+ * @see org.mozilla.javascript.ScriptableObject#deleteProperty
*/
public void delete(String name);
@@ -249,15 +249,15 @@ public interface Scriptable {
* The property is specified by an integral index
* as defined for get
.
*
- * For a more convenient form of this method,
- * see deleteProperty in FlattenedObject.
+ * To delete properties defined in a prototype chain,
+ * see deleteProperty in ScriptableObject.
*
* Identical to delete(String)
except that
* an integral index is used to select the property.
*
* @param index the numeric index for the property
* @see org.mozilla.javascript.Scriptable#get
- * @see org.mozilla.javascript.FlattenedObject#deleteProperty
+ * @see org.mozilla.javascript.ScriptableObject#deleteProperty
*/
public void delete(int index);
diff --git a/js/rhino/src/org/mozilla/javascript/ScriptableObject.java b/js/rhino/src/org/mozilla/javascript/ScriptableObject.java
index 25863d378f5..0166aadef46 100644
--- a/js/rhino/src/org/mozilla/javascript/ScriptableObject.java
+++ b/js/rhino/src/org/mozilla/javascript/ScriptableObject.java
@@ -524,17 +524,17 @@ public abstract class ScriptableObject implements Scriptable {
*/
public Object getDefaultValue(Class typeHint) {
Object val;
- FlattenedObject f = new FlattenedObject(this);
Context cx = null;
try {
for (int i=0; i < 2; i++) {
if (typeHint == ScriptRuntime.StringClass ? i == 0 : i == 1) {
- Function fun = getFunctionProperty(f, "toString");
- if (fun == null)
+ Object v = getProperty(this, "toString");
+ if (!(v instanceof Function))
continue;
+ Function fun = (Function) v;
if (cx == null)
cx = Context.getContext();
- val = fun.call(cx, fun.getParentScope(), f.getObject(),
+ val = fun.call(cx, fun.getParentScope(), this,
ScriptRuntime.emptyArgs);
} else {
String hint;
@@ -566,14 +566,14 @@ public abstract class ScriptableObject implements Scriptable {
throw Context.reportRuntimeError(
Context.getMessage("msg.invalid.type", args));
}
- Function fun = getFunctionProperty(f, "valueOf");
- if (fun == null)
+ Object v = getProperty(this, "valueOf");
+ if (!(v instanceof Function))
continue;
+ Function fun = (Function) v;
Object[] args = { hint };
if (cx == null)
cx = Context.getContext();
- val = fun.call(cx, fun.getParentScope(), f.getObject(),
- args);
+ val = fun.call(cx, fun.getParentScope(), this, args);
}
if (val != null && (val == Undefined.instance ||
!(val instanceof Scriptable) ||
@@ -1326,7 +1326,146 @@ public abstract class ScriptableObject implements Scriptable {
public boolean isSealed() {
return count == -1;
}
-
+
+ /**
+ * Gets a named property from an object or any object in its prototype chain.
+ *
+ * Searches the prototype chain for a property named name
.
+ *
+ * @param obj a JavaScript object
+ * @param name a property name
+ * @return the value of a property with name name
found in
+ * obj
or any object in its prototype chain, or
+ * Scriptable.NOT_FOUND
if not found
+ */
+ public static Object getProperty(Scriptable obj, String name) {
+ Scriptable start = obj;
+ Object result;
+ do {
+ result = obj.get(name, start);
+ if (result != Scriptable.NOT_FOUND)
+ break;
+ obj = obj.getPrototype();
+ } while (obj != null);
+ return result;
+ }
+
+ /**
+ * Gets an indexed property from an object or any object in its prototype chain.
+ *
+ * Searches the prototype chain for a property with integral index
+ * index
. Note that if you wish to look for properties with numerical
+ * but non-integral indicies, you should use getProperty(Scriptable,String) with
+ * the string value of the index.
+ *
+ * @param obj a JavaScript object
+ * @param index an integral index
+ * @return the value of a property with index index
found in
+ * obj
or any object in its prototype chain, or
+ * Scriptable.NOT_FOUND
if not found
+ */
+ public static Object getProperty(Scriptable obj, int index) {
+ Scriptable start = obj;
+ Object result;
+ do {
+ result = obj.get(index, start);
+ if (result != Scriptable.NOT_FOUND)
+ break;
+ obj = obj.getPrototype();
+ } while (obj != null);
+ return result;
+ }
+
+ /**
+ * Puts a named property in an object or in an object in its prototype chain.
+ *
+ * Seaches for the named property in the prototype chain. If it is found,
+ * the value of the property is changed. If it is not found, a new
+ * property is added in obj
.
+ * @param obj a JavaScript object
+ * @param name a property name
+ * @param value any JavaScript value accepted by Scriptable.put
+ */
+ public static void putProperty(Scriptable obj, String name, Object value) {
+ Scriptable base = getBase(obj, name);
+ if (base == null)
+ base = obj;
+ base.put(name, obj, value);
+ }
+
+ /**
+ * Puts an indexed property in an object or in an object in its prototype chain.
+ *
+ * Seaches for the indexed property in the prototype chain. If it is found,
+ * the value of the property is changed. If it is not found, a new
+ * property is added in obj
.
+ * @param obj a JavaScript object
+ * @param index a property index
+ * @param value any JavaScript value accepted by Scriptable.put
+ */
+ public static void putProperty(Scriptable obj, int index, Object value) {
+ Scriptable base = getBase(obj, index);
+ if (base == null)
+ base = obj;
+ base.put(index, obj, value);
+ }
+
+ /**
+ * Removes the property from an object or its prototype chain.
+ *
+ * Searches for a property with name
in obj or
+ * its prototype chain. If it is found, the object's delete
+ * method is called.
+ * @param obj a JavaScript object
+ * @param name a property name
+ * @return true if the property doesn't exist or was successfully removed
+ */
+ public static boolean deleteProperty(Scriptable obj, String name) {
+ Scriptable base = getBase(obj, name);
+ if (base == null)
+ return true;
+ base.delete(name);
+ return base.get(name, obj) == NOT_FOUND;
+ }
+
+ /**
+ * Removes the property from an object or its prototype chain.
+ *
+ * Searches for a property with index
in obj or
+ * its prototype chain. If it is found, the object's delete
+ * method is called.
+ * @param obj a JavaScript object
+ * @param index a property index
+ * @return true if the property doesn't exist or was successfully removed
+ */
+ public static boolean deleteProperty(Scriptable obj, int index) {
+ Scriptable base = getBase(obj, index);
+ if (base == null)
+ return true;
+ base.delete(index);
+ return base.get(index, obj) == NOT_FOUND;
+ }
+
+ private static Scriptable getBase(Scriptable obj, String s) {
+ Scriptable m = obj;
+ while (m != null) {
+ if (m.has(s, obj))
+ return m;
+ m = m.getPrototype();
+ }
+ return null;
+ }
+
+ private static Scriptable getBase(Scriptable obj, int index) {
+ Scriptable m = obj;
+ while (m != null) {
+ if (m.has(index, obj))
+ return m;
+ m = m.getPrototype();
+ }
+ return null;
+ }
+
/**
* Adds a property attribute to all properties.
*/
@@ -1476,16 +1615,6 @@ public abstract class ScriptableObject implements Scriptable {
slots = newSlots;
}
- private Function getFunctionProperty(FlattenedObject f, String name) {
- Object val = f.getProperty(name);
- if (val == null || !(val instanceof FlattenedObject))
- return null;
- Scriptable s = ((FlattenedObject) val).getObject();
- if (s instanceof Function)
- return (Function) s;
- return null;
- }
-
private static Hashtable getExclusionList() {
if (exclusionList != null)
return exclusionList;