mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
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:
parent
2faa2566a0
commit
5207d03135
@ -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) {
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user