1. Optimizing getClassPrototype and getDefaultValue in ScriptableObject.

2. Start of the changes for simpler to use IdScriptable implementation: new utility functions in IdFunction and removal of Context argument from IdScriptable.fillConstructorProperties.
This commit is contained in:
igor%mir2.org 2004-07-28 07:12:46 +00:00
parent 2faa2566a0
commit 5207d03135
7 changed files with 97 additions and 82 deletions

View File

@ -53,8 +53,7 @@ public class BaseFunction extends IdScriptable implements Function {
obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);
}
protected void fillConstructorProperties
(Context cx, IdFunction ctor, boolean sealed)
protected void fillConstructorProperties(IdFunction ctor, boolean sealed)
{
// Fix up bootstrapping problem: getPrototype of the IdFunction
// can not return Function.prototype because Function object is not
@ -327,7 +326,7 @@ public class BaseFunction extends IdScriptable implements Function {
return functionName;
}
private Object getPrototypeProperty() {
Object getPrototypeProperty() {
Object result = prototypeProperty;
if (result == null) {
synchronized (this) {

View File

@ -67,16 +67,21 @@ public class IdFunction extends BaseFunction
setImmunePrototypeProperty(prototypeProperty);
}
public final void exportAsScopeProperty(boolean seal)
public final void addAsProperty(Scriptable target)
{
exportAsScopeProperty(ScriptableObject.DONTENUM, seal);
addAsProperty(target, false);
}
public void exportAsScopeProperty(int attributes, boolean seal)
public final void addAsProperty(Scriptable target, boolean seal)
{
if (seal) { sealObject(); }
ScriptableObject.defineProperty(getParentScope(), functionName, this,
attributes);
ScriptableObject.defineProperty(target, functionName, this,
ScriptableObject.DONTENUM);
}
public void exportAsScopeProperty(boolean seal)
{
addAsProperty(getParentScope(), seal);
}
public Scriptable getPrototype()

View File

@ -417,40 +417,30 @@ public abstract class IdScriptable extends ScriptableObject
public void addAsPrototype(int maxId, Context cx, Scriptable scope,
boolean sealed)
{
setMaxId(maxId);
int constructorId = mapNameToId("constructor");
if (constructorId == 0) {
// It is a bug to call this function without id for constructor
throw new RuntimeException("No id for constructor property");
}
// Set scope and prototype unless IdScriptable is top level scope itself
if (scope != this && scope != null) {
setParentScope(scope);
setPrototype(getObjectPrototype(scope));
}
IdFunction ctor = newIdFunction(getClassName(), constructorId, scope);
setMaxId(maxId);
IdFunction ctor = newConstructor(scope);
ctor.markAsConstructor(this);
fillConstructorProperties(cx, ctor, sealed);
cacheIdValue(constructorId, ctor);
fillConstructorProperties(ctor, sealed);
cacheIdValue(ctor.methodId(), ctor);
ctor.exportAsScopeProperty(sealed);
}
protected void fillConstructorProperties
(Context cx, IdFunction ctor, boolean sealed)
protected void fillConstructorProperties(IdFunction ctor, boolean sealed)
{
}
protected void addIdFunctionProperty
(Scriptable obj, int id, boolean sealed)
{
Scriptable scope = ScriptableObject.getTopLevelScope(this);
Scriptable scope = ScriptableObject.getTopLevelScope(obj);
IdFunction f = newIdFunction(id, scope);
if (sealed) { f.sealObject(); }
defineProperty(obj, getIdName(id), f, DONTENUM);
f.addAsProperty(obj, sealed);
}
/**
@ -493,6 +483,15 @@ public abstract class IdScriptable extends ScriptableObject
return f;
}
protected IdFunction newConstructor(Scriptable scope)
{
int constructorId = mapNameToId("constructor");
if (constructorId == 0) {
throw new IllegalStateException("No id for constructor property");
}
return newIdFunction(getClassName(), constructorId, scope);
}
protected final Object wrap_double(double x)
{
return (x == x) ? new Double(x) : ScriptRuntime.NaNobj;

View File

@ -88,13 +88,12 @@ final class NativeDate extends IdScriptable
return date;
}
protected void fillConstructorProperties
(Context cx, IdFunction ctor, boolean sealed)
protected void fillConstructorProperties(IdFunction ctor, boolean sealed)
{
addIdFunctionProperty(ctor, ConstructorId_now, sealed);
addIdFunctionProperty(ctor, ConstructorId_parse, sealed);
addIdFunctionProperty(ctor, ConstructorId_UTC, sealed);
super.fillConstructorProperties(cx, ctor, sealed);
super.fillConstructorProperties(ctor, sealed);
}
public Object execMethod(IdFunction f, Context cx, Scriptable scope,

View File

@ -68,8 +68,7 @@ final class NativeNumber extends IdScriptable {
return "Number";
}
protected void fillConstructorProperties
(Context cx, IdFunction ctor, boolean sealed)
protected void fillConstructorProperties(IdFunction ctor, boolean sealed)
{
final int attr = ScriptableObject.DONTENUM |
ScriptableObject.PERMANENT |
@ -83,7 +82,7 @@ final class NativeNumber extends IdScriptable {
ctor.defineProperty("MAX_VALUE", wrap_double(Double.MAX_VALUE), attr);
ctor.defineProperty("MIN_VALUE", wrap_double(Double.MIN_VALUE), attr);
super.fillConstructorProperties(cx, ctor, sealed);
super.fillConstructorProperties(ctor, sealed);
}
public Object execMethod(IdFunction f, Context cx, Scriptable scope,

View File

@ -65,11 +65,10 @@ final class NativeString extends IdScriptable {
return "String";
}
protected void fillConstructorProperties
(Context cx, IdFunction ctor, boolean sealed)
protected void fillConstructorProperties(IdFunction ctor, boolean sealed)
{
addIdFunctionProperty(ctor, ConstructorId_fromCharCode, sealed);
super.fillConstructorProperties(cx, ctor, sealed);
super.fillConstructorProperties(ctor, sealed);
}
protected int getIdAttributes(int id)

View File

@ -500,33 +500,39 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
*
* See ECMA 8.6.2.6.
*/
public Object getDefaultValue(Class typeHint) {
Object val;
public Object getDefaultValue(Class typeHint)
{
Context cx = null;
for (int i=0; i < 2; i++) {
if (typeHint == ScriptRuntime.StringClass ? i == 0 : i == 1) {
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(), this,
ScriptRuntime.emptyArgs);
boolean tryToString;
if (typeHint == ScriptRuntime.StringClass) {
tryToString = (i == 0);
} else {
tryToString = (i == 1);
}
String methodName;
Object[] args;
if (tryToString) {
methodName = "toString";
args = ScriptRuntime.emptyArgs;
} else {
methodName = "valueOf";
args = new Object[1];
String hint;
if (typeHint == null)
if (typeHint == null) {
hint = "undefined";
else if (typeHint == ScriptRuntime.StringClass)
} else if (typeHint == ScriptRuntime.StringClass) {
hint = "string";
else if (typeHint == ScriptRuntime.ScriptableClass)
} else if (typeHint == ScriptRuntime.ScriptableClass) {
hint = "object";
else if (typeHint == ScriptRuntime.FunctionClass)
} else if (typeHint == ScriptRuntime.FunctionClass) {
hint = "function";
else if (typeHint == ScriptRuntime.BooleanClass ||
typeHint == Boolean.TYPE)
} else if (typeHint == ScriptRuntime.BooleanClass
|| typeHint == Boolean.TYPE)
{
hint = "boolean";
else if (typeHint == ScriptRuntime.NumberClass ||
} else if (typeHint == ScriptRuntime.NumberClass ||
typeHint == ScriptRuntime.ByteClass ||
typeHint == Byte.TYPE ||
typeHint == ScriptRuntime.ShortClass ||
@ -537,33 +543,38 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
typeHint == Float.TYPE ||
typeHint == ScriptRuntime.DoubleClass ||
typeHint == Double.TYPE)
{
hint = "number";
else {
} else {
throw Context.reportRuntimeError1(
"msg.invalid.type", typeHint.toString());
}
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(), this, args);
args[0] = hint;
}
if (val != null && (val == Undefined.instance ||
!(val instanceof Scriptable) ||
typeHint == ScriptRuntime.ScriptableClass ||
typeHint == ScriptRuntime.FunctionClass))
{
return val;
}
if (val instanceof NativeJavaObject) {
// Let a wrapped java.lang.String pass for a primitive
// string.
Object u = ((Wrapper) val).unwrap();
if (u instanceof String)
return u;
Object v = getProperty(this, methodName);
if (!(v instanceof Function))
continue;
Function fun = (Function) v;
if (cx == null)
cx = Context.getContext();
v = fun.call(cx, fun.getParentScope(), this, args);
if (v != null) {
if (!(v instanceof Scriptable)) {
return v;
}
if (v == Undefined.instance
|| typeHint == ScriptRuntime.ScriptableClass
|| typeHint == ScriptRuntime.FunctionClass)
{
return v;
}
if (tryToString && v instanceof Wrapper) {
// Let a wrapped java.lang.String pass for a primitive
// string.
Object u = ((Wrapper)v).unwrap();
if (u instanceof String)
return u;
}
}
}
// fall through to error
@ -1160,15 +1171,19 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
{
scope = getTopLevelScope(scope);
Object ctor = getProperty(scope, className);
if (ctor == NOT_FOUND || !(ctor instanceof Scriptable))
Object proto;
if (ctor instanceof BaseFunction) {
proto = ((BaseFunction)ctor).getPrototypeProperty();
} else if (ctor instanceof Scriptable) {
Scriptable ctorObj = (Scriptable)ctor;
proto = ctorObj.get("prototype", ctorObj);
} else {
return null;
Scriptable ctorObj = (Scriptable) ctor;
if (!ctorObj.has("prototype", ctorObj))
return null;
Object proto = ctorObj.get("prototype", ctorObj);
if (!(proto instanceof Scriptable))
return null;
return (Scriptable) proto;
}
if (proto instanceof Scriptable) {
return (Scriptable)proto;
}
return null;
}
/**