This patch changes NativeError.java to store message and name properties

in fields of the object itself instead of using the standard property
hashtable in ScriptableObject.java. This saves 3 object instances per
NativeError (2 slot entries and hashtable array itself) and given the
fact that NativeGlobal defines a few permanent Error instances, it is
visible saving even after taking into account code size increase.

The change also gives a good test of IdScriptable implementation.

-----

This patch introduces the uniform decompile method for NativeFunction
and IdFunction with the signature:

public String decompile(Context cx, int indent, boolean justbody)

instead of NativeFunction.decompile(int indent, boolean toplevel,
boolean justbody) and IdScriptable.toStringForScript(Context cx) and
replaces the special treatment of NativeJavaMethod in
NativeFunction.jsFunction_toString by overriding decompile in
NativeJavaMethod

-----

This patch adds getFunctionName to NativeFunction to return function
name and replaces few places with jsGet_name usage by getFunctionName

The patch was made via
diff -ru javascript.0 javascript > name_patch
from org/mozilla directory
This commit is contained in:
nboyd%atg.com 2001-05-21 15:04:54 +00:00
Родитель 075d5ed2c8
Коммит e4294421c9
8 изменённых файлов: 145 добавлений и 56 удалений

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

@ -916,7 +916,7 @@ public class Context {
{ {
NativeScript ns = (NativeScript) script; NativeScript ns = (NativeScript) script;
ns.initScript(scope); ns.initScript(scope);
return ns.decompile(indent, true, false); return ns.decompile(this, indent, false);
} }
/** /**
@ -934,7 +934,9 @@ public class Context {
*/ */
public String decompileFunction(Function fun, int indent) { public String decompileFunction(Function fun, int indent) {
if (fun instanceof NativeFunction) if (fun instanceof NativeFunction)
return ((NativeFunction)fun).decompile(indent, true, false); return ((NativeFunction)fun).decompile(this, indent, false);
else if (fun instanceof IdFunction)
return ((IdFunction)fun).decompile(this, indent, false);
else else
return "function " + fun.getClassName() + return "function " + fun.getClassName() +
"() {\n\t[native code]\n}\n"; "() {\n\t[native code]\n}\n";
@ -955,7 +957,9 @@ public class Context {
*/ */
public String decompileFunctionBody(Function fun, int indent) { public String decompileFunctionBody(Function fun, int indent) {
if (fun instanceof NativeFunction) if (fun instanceof NativeFunction)
return ((NativeFunction)fun).decompile(indent, true, true); return ((NativeFunction)fun).decompile(this, indent, true);
else if (fun instanceof IdFunction)
return ((IdFunction)fun).decompile(this, indent, true);
else else
// not sure what the right response here is. JSRef currently // not sure what the right response here is. JSRef currently
// dumps core. // dumps core.

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

@ -164,11 +164,14 @@ public class IdFunction extends ScriptableObject implements Function
return (Scriptable) protoVal; return (Scriptable) protoVal;
} }
protected Object toStringForScript(Context cx) { public String decompile(Context cx, int indent, boolean justbody) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
if (!justbody) {
sb.append("function "); sb.append("function ");
sb.append(methodName); sb.append(methodName);
sb.append("() { [native code for "); sb.append("() { ");
}
sb.append("[native code for ");
if (master instanceof Scriptable) { if (master instanceof Scriptable) {
Scriptable smaster = (Scriptable)master; Scriptable smaster = (Scriptable)master;
sb.append(smaster.getClassName()); sb.append(smaster.getClassName());
@ -177,7 +180,7 @@ public class IdFunction extends ScriptableObject implements Function
sb.append(methodName); sb.append(methodName);
sb.append(", arity="); sb.append(", arity=");
sb.append(getArity()); sb.append(getArity());
sb.append("] }"); sb.append(justbody ? "]\n" : "] }\n");
return sb.toString(); return sb.toString();
} }

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

@ -48,11 +48,40 @@ public class NativeError extends IdScriptable {
public static void init(Context cx, Scriptable scope, boolean sealed) { public static void init(Context cx, Scriptable scope, boolean sealed) {
NativeError obj = new NativeError(); NativeError obj = new NativeError();
obj.prototypeFlag = true; obj.prototypeFlag = true;
obj.defineProperty("message", "", ScriptableObject.EMPTY); obj.messageValue = "";
obj.defineProperty("name", "Error", ScriptableObject.EMPTY); obj.nameValue = "Error";
obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed); obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);
} }
protected int getIdDefaultAttributes(int id) {
if (id == Id_message || id == Id_name) { return EMPTY; }
return super.getIdDefaultAttributes(id);
}
protected boolean hasIdValue(int id) {
if (id == Id_message) { return messageValue != NOT_FOUND; }
if (id == Id_name) { return nameValue != NOT_FOUND; }
return super.hasIdValue(id);
}
protected Object getIdValue(int id) {
if (id == Id_message) { return messageValue; }
if (id == Id_name) { return nameValue; }
return super.getIdValue(id);
}
protected void setIdValue(int id, Object value) {
if (id == Id_message) { messageValue = value; return; }
if (id == Id_name) { nameValue = value; return; }
super.setIdValue(id, value);
}
protected void deleteIdValue(int id) {
if (id == Id_message) { messageValue = NOT_FOUND; return; }
if (id == Id_name) { nameValue = NOT_FOUND; return; }
super.deleteIdValue(id);
}
public int methodArity(int methodId) { public int methodArity(int methodId) {
if (prototypeFlag) { if (prototypeFlag) {
if (methodId == Id_constructor) return 1; if (methodId == Id_constructor) return 1;
@ -71,7 +100,7 @@ public class NativeError extends IdScriptable {
return jsConstructor(cx, args, f, thisObj == null); return jsConstructor(cx, args, f, thisObj == null);
} }
else if (methodId == Id_toString) { else if (methodId == Id_toString) {
return realThis(thisObj, f).jsFunction_toString(); return realThis(thisObj, f).toString();
} }
} }
return super.execMethod(methodId, f, cx, scope, thisObj, args); return super.execMethod(methodId, f, cx, scope, thisObj, args);
@ -89,7 +118,7 @@ public class NativeError extends IdScriptable {
{ {
NativeError result = new NativeError(); NativeError result = new NativeError();
if (args.length >= 1) if (args.length >= 1)
result.put("message", result, cx.toString(args[0])); result.messageValue = ScriptRuntime.toString(args[0]);
result.setPrototype(getClassPrototype(funObj, "Error")); result.setPrototype(getClassPrototype(funObj, "Error"));
return result; return result;
} }
@ -102,21 +131,23 @@ public class NativeError extends IdScriptable {
return getName() + ": " + getMessage(); return getName() + ": " + getMessage();
} }
private String jsFunction_toString() {
return toString();
}
public String getName() { public String getName() {
return ScriptRuntime.toString( Object val = nameValue;
ScriptRuntime.getProp(this, "name", this)); return ScriptRuntime.toString(val != NOT_FOUND ? val
: Undefined.instance);
} }
public String getMessage() { public String getMessage() {
return ScriptRuntime.toString( Object val = messageValue;
ScriptRuntime.getProp(this, "message", this)); return ScriptRuntime.toString(val != NOT_FOUND ? val
: Undefined.instance);
} }
protected int maxInstanceId() { return MAX_INSTANCE_ID; }
protected String getIdName(int id) { protected String getIdName(int id) {
if (id == Id_message) { return "message"; }
if (id == Id_name) { return "name"; }
if (prototypeFlag) { if (prototypeFlag) {
if (id == Id_constructor) return "constructor"; if (id == Id_constructor) return "constructor";
if (id == Id_toString) return "toString"; if (id == Id_toString) return "toString";
@ -126,10 +157,28 @@ public class NativeError extends IdScriptable {
// #string_id_map# // #string_id_map#
private static final int
Id_message = 1,
Id_name = 2,
MAX_INSTANCE_ID = 2;
protected int mapNameToId(String s) { protected int mapNameToId(String s) {
if (!prototypeFlag) { return 0; }
int id; int id;
// #generated# Last update: 2001-04-23 10:03:24 CEST // #generated# Last update: 2001-05-19 21:55:23 CEST
L0: { id = 0; String X = null;
int s_length = s.length();
if (s_length==4) { X="name";id=Id_name; }
else if (s_length==7) { X="message";id=Id_message; }
if (X!=null && X!=s && !X.equals(s)) id = 0;
}
// #/generated#
// #/string_id_map#
if (id != 0 || !prototypeFlag) { return id; }
// #string_id_map#
// #generated# Last update: 2001-05-19 21:55:23 CEST
L0: { id = 0; String X = null; L0: { id = 0; String X = null;
int s_length = s.length(); int s_length = s.length();
if (s_length==8) { X="toString";id=Id_toString; } if (s_length==8) { X="toString";id=Id_toString; }
@ -141,11 +190,15 @@ public class NativeError extends IdScriptable {
} }
private static final int private static final int
Id_constructor = 1, Id_constructor = MAX_INSTANCE_ID + 1,
Id_toString = 2, Id_toString = MAX_INSTANCE_ID + 2,
MAX_PROTOTYPE_ID = 2;
MAX_PROTOTYPE_ID = MAX_INSTANCE_ID + 2;
// #/string_id_map# // #/string_id_map#
private Object messageValue = NOT_FOUND;
private Object nameValue = NOT_FOUND;
private boolean prototypeFlag; private boolean prototypeFlag;
} }

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

@ -186,20 +186,36 @@ public class NativeFunction extends ScriptableObject implements Function {
* between function header and function body that rhino * between function header and function body that rhino
* decompilation does not. * decompilation does not.
* *
* @param indent How much to indent the decompiled result * @param cx Cuirrent context
* *
* @param toplevel Whether this is the first call or a recursive * @param indent How much to indent the decompiled result
* call of decompile. (Not whether the function is defined at the
* top level of script evaluation.)
* *
* @param justbody Whether the decompilation should omit the * @param justbody Whether the decompilation should omit the
* function header and trailing brace. * function header and trailing brace.
*/ */
public String decompile(int indent, boolean toplevel, boolean justbody) { public String decompile(Context cx, int indent, boolean justbody) {
if (source == null) StringBuffer result = new StringBuffer();
return "function " + jsGet_name() + decompile(indent, true, justbody, result);
"() {\n\t[native code]\n}\n"; return result.toString();
}
private void decompile(int indent, boolean toplevel, boolean justbody,
StringBuffer result)
{
if (source == null) {
if (!justbody) {
result.append("function ");
result.append(getFunctionName());
result.append("() {\n\t");
}
result.append("[native code]\n");
if (!justbody) {
result.append("}\n");
}
return;
}
// Spew tokens in source, for debugging. // Spew tokens in source, for debugging.
// as TYPE number char // as TYPE number char
@ -224,8 +240,6 @@ public class NativeFunction extends ScriptableObject implements Function {
System.err.println(); System.err.println();
} }
StringBuffer result = new StringBuffer();
int i = 0; int i = 0;
if (source.length() > 0) { if (source.length() > 0) {
@ -408,9 +422,8 @@ public class NativeFunction extends ScriptableObject implements Function {
} }
throw Context.reportRuntimeError(message); throw Context.reportRuntimeError(message);
} }
result.append(nestedFunctions[functionNumber].decompile(indent, nestedFunctions[functionNumber].
false, decompile(indent, false, false, result);
false));
break; break;
} }
case TokenStream.COMMA: case TokenStream.COMMA:
@ -827,29 +840,20 @@ public class NativeFunction extends ScriptableObject implements Function {
// add that trailing newline if it's an outermost function. // add that trailing newline if it's an outermost function.
if (toplevel && !justbody) if (toplevel && !justbody)
result.append('\n'); result.append('\n');
return result.toString();
} }
public static Object jsFunction_toString(Context cx, Scriptable thisObj, public static Object jsFunction_toString(Context cx, Scriptable thisObj,
Object[] args, Function funObj) Object[] args, Function funObj)
{ {
int indent = ScriptRuntime.toInt32(args, 0);
Object val = thisObj.getDefaultValue(ScriptRuntime.FunctionClass); Object val = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);
if (val instanceof NativeFunction) { if (val instanceof NativeFunction) {
NativeFunction funVal = (NativeFunction)val; NativeFunction funVal = (NativeFunction)val;
if (funVal instanceof NativeJavaMethod) { return funVal.decompile(cx, indent, false);
return "\nfunction " + funVal.jsGet_name() +
"() {/*\n" + val.toString() + "*/}\n";
}
int indent = 0;
if (args.length > 0)
indent = (int)ScriptRuntime.toNumber(args[0]);
return funVal.decompile(indent, true, false);
} }
else if (val instanceof IdFunction) { else if (val instanceof IdFunction) {
IdFunction funVal = (IdFunction)val; IdFunction funVal = (IdFunction)val;
return funVal.toStringForScript(cx); return funVal.decompile(cx, indent, false);
} }
throw NativeGlobal.typeError1 throw NativeGlobal.typeError1
("msg.incompat.call", "toString", thisObj); ("msg.incompat.call", "toString", thisObj);
@ -970,7 +974,7 @@ public class NativeFunction extends ScriptableObject implements Function {
return argCount; return argCount;
} }
public String jsGet_name() { public String getFunctionName() {
if (functionName == null) if (functionName == null)
return ""; return "";
if (functionName.equals("anonymous")) { if (functionName.equals("anonymous")) {
@ -981,6 +985,10 @@ public class NativeFunction extends ScriptableObject implements Function {
return functionName; return functionName;
} }
public String jsGet_name() {
return getFunctionName();
}
private NativeCall getActivation(Context cx) { private NativeCall getActivation(Context cx) {
NativeCall activation = cx.currentActivation; NativeCall activation = cx.currentActivation;
while (activation != null) { while (activation != null) {

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

@ -153,15 +153,32 @@ public class NativeJavaMethod extends NativeFunction implements Function {
} }
} }
public String decompile(Context cx, int indent, boolean justbody) {
StringBuffer sb = new StringBuffer();
if (!justbody) {
sb.append("function ");
sb.append(getFunctionName());
sb.append("() {");
}
sb.append("/*\n");
toString(sb);
sb.append(justbody ? "*/\n" : "*/}\n");
return sb.toString();
}
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
toString(sb);
return sb.toString();
}
private void toString(StringBuffer sb) {
for (int i=0; i < methods.length; i++) { for (int i=0; i < methods.length; i++) {
sb.append(javaSignature(methods[i].getReturnType())); sb.append(javaSignature(methods[i].getReturnType()));
sb.append(' '); sb.append(' ');
sb.append(signature(methods[i])); sb.append(signature(methods[i]));
sb.append('\n'); sb.append('\n');
} }
return sb.toString();
} }
public Object call(Context cx, Scriptable scope, Scriptable thisObj, public Object call(Context cx, Scriptable scope, Scriptable thisObj,

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

@ -134,10 +134,14 @@ public class NativeScript extends NativeFunction implements Script {
return cx.decompileScript(thisScript, scope, 0); return cx.decompileScript(thisScript, scope, 0);
} }
public String jsGet_name() {
return getFunctionName();
}
/* /*
* Override method in NativeFunction to avoid ever returning "anonymous" * Override method in NativeFunction to avoid ever returning "anonymous"
*/ */
public String jsGet_name() { public String getFunctionName() {
return ""; return "";
} }

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

@ -1968,7 +1968,7 @@ public class ScriptRuntime {
result.setPrototype(ScriptableObject.getClassPrototype(scope, "Function")); result.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));
result.setParentScope(scope); result.setParentScope(scope);
String fnName = result.jsGet_name(); String fnName = result.getFunctionName();
if (setName && fnName != null && fnName.length() != 0 && if (setName && fnName != null && fnName.length() != 0 &&
!fnName.equals("anonymous")) !fnName.equals("anonymous"))
{ {

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

@ -273,7 +273,7 @@ public class NativeRegExp extends ScriptableObject implements Function {
Object[] args, Scriptable scopeObj, Object[] args, Scriptable scopeObj,
int matchType, Function funObj) { int matchType, Function funObj) {
if (!(thisObj instanceof NativeRegExp)) { if (!(thisObj instanceof NativeRegExp)) {
Object[] errArgs = { ((NativeFunction) funObj).jsGet_name() }; Object[] errArgs = { ((NativeFunction) funObj).getFunctionName() };
throw NativeGlobal.constructError( throw NativeGlobal.constructError(
cx, "TypeError", cx, "TypeError",
ScriptRuntime.getMessage( ScriptRuntime.getMessage(