bug fixes for handling of prototype and __proto__

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4188 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2011-06-22 21:23:49 +00:00
parent 91628b4d1b
commit 201b28eea0
4 changed files with 64 additions and 14 deletions

View File

@ -1420,6 +1420,26 @@ public class RhinoToAstTranslator {
return result;
}
case Token.GET_REF: {
// read of __proto__
// first and only child c1 is of type Token.REF_SPECIAL whose NAME_PROP property should be "__proto__".
// c1 has a single child, the base pointer for the reference
Node child1 = n.getFirstChild();
assert child1.getType() == Token.REF_SPECIAL;
assert child1.getProp(Node.NAME_PROP).equals("__proto__");
Node receiver = child1.getFirstChild();
assert child1.getNext() == null;
CAstNode rcvr = walkNodes(receiver, context);
final CAstNode result = Ast.makeNode(CAstNode.OBJECT_REF, rcvr, Ast.makeConstant("__proto__"));
if (context.getCatchTarget() != null) {
context.cfg().map(result, result);
context.cfg().add(result, context.getCatchTarget(), JavaScriptTypes.TypeError);
}
return result;
}
case Token.SETPROP:
case Token.SETELEM: {
@ -1432,6 +1452,23 @@ public class RhinoToAstTranslator {
return Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, rcvr, walkNodes(elt, context)),
walkNodes(val, context));
}
case Token.SET_REF: {
// first child c1 is of type Token.REF_SPECIAL whose NAME_PROP property should be "__proto__".
// c1 has a single child, the base pointer for the reference
// second child c2 is RHS of assignment
Node child1 = n.getFirstChild();
assert child1.getType() == Token.REF_SPECIAL;
assert child1.getProp(Node.NAME_PROP).equals("__proto__");
Node receiver = child1.getFirstChild();
Node val = child1.getNext();
CAstNode rcvr = walkNodes(receiver, context);
return Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, rcvr, Ast.makeConstant("__proto__")),
walkNodes(val, context));
}
case Token.DELPROP: {
Node receiver = n.getFirstChild();

View File

@ -71,6 +71,8 @@ Object.prototype = {
prototype: null,
__proto__: null,
constructor: Object,
toString: function toString() {
@ -97,6 +99,7 @@ Object.prototype = {
};
/************************************************************************/
/* Function properties, see spec 15.3 */
/************************************************************************/
@ -105,6 +108,8 @@ Function.prototype = {
constructor: Function,
__proto__: Object.prototype,
toString: function functionToString() {
return primitive("FunctionToString", this);
},
@ -126,7 +131,7 @@ Function.prototype = {
Array.prototype = {
prototype: Object.prototype,
__proto__: Object.prototype,
constructor: Array,
@ -245,7 +250,7 @@ Array.prototype = {
String.prototype = {
prototype: Object.prototype,
__proto__: Object.prototype,
constructor: String,
@ -321,7 +326,7 @@ String.prototype = {
Number.prototype = {
prototype: Object.prototype,
__proto__: Object.prototype,
constructor: Number,
@ -409,7 +414,7 @@ Math = {
RegExp.prototype = {
prototype: Object.prototype,
__proto__: Object.prototype,
constructor: RegExp

View File

@ -42,6 +42,10 @@ import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
/**
* generates instructions to simulate the semantics of JS constructor invocations
*
*/
public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
private static final boolean DEBUG = false;
@ -88,7 +92,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.NewInstruction(5, NewSiteReference.make(S.getNextProgramCounter(), cls.getReference())));
S.addStatement(insts.PutInstruction(5, 4, "prototype"));
S.addStatement(insts.PutInstruction(5, 4, "__proto__"));
S.getNextProgramCounter();
S.addConstant(new Integer(8), new ConstantValue(value));
@ -111,7 +115,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.NewInstruction(6, NewSiteReference.make(S.getNextProgramCounter(), cls.getReference())));
S.addStatement(insts.PutInstruction(6, 5, "prototype"));
S.addStatement(insts.PutInstruction(6, 5, "__proto__"));
S.getNextProgramCounter();
S.addStatement(insts.PutInstruction(6, 2, "$value"));
@ -138,6 +142,9 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
}
}
/**
* create a method for constructing an Object with no arguments passed
*/
private IMethod makeNullaryObjectConstructor(IClass cls) {
JSInstructionFactory insts = (JSInstructionFactory)cls.getClassLoader().getInstructionFactory();
MethodReference ref = JavaScriptMethods.makeCtorReference(JavaScriptTypes.Object);
@ -148,7 +155,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.NewInstruction(5, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object)));
S.addStatement(insts.PutInstruction(5, 4, "prototype"));
S.addStatement(insts.PutInstruction(5, 4, "__proto__"));
S.getNextProgramCounter();
S.addStatement(insts.ReturnInstruction(5, false));
@ -205,7 +212,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.NewInstruction(6, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Array)));
S.addStatement(insts.PutInstruction(6, 5, "prototype"));
S.addStatement(insts.PutInstruction(6, 5, "__proto__"));
S.getNextProgramCounter();
S.addStatement(insts.PutInstruction(6, 2, "length"));
@ -230,7 +237,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
insts.NewInstruction(nargs + 5, NewSiteReference.make(S.getNextProgramCounter(),
JavaScriptTypes.Array)));
S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "prototype"));
S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__"));
S.getNextProgramCounter();
S.addConstant(new Integer(nargs + 7), new ConstantValue(nargs));
@ -355,6 +362,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.NewInstruction(7, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object)));
// TODO fix these writes to operate on __proto__, once we're sure we're doing the right thing here
S.addStatement(insts.PutInstruction(7, 4, "prototype"));
S.getNextProgramCounter();
@ -466,7 +474,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
NewSiteReference.make(S.getNextProgramCounter(),
JavaScriptTypes.Object)));
S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "prototype"));
S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__"));
S.getNextProgramCounter();
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());

View File

@ -120,8 +120,8 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
CAstNode get, result;
String receiverTemp = TEMP_NAME + (readTempCounter++);
String elt = (String) element.getValue();
if (elt.equals("prototype")) {
result = Ast.makeNode(CAstNode.BLOCK_EXPR, get = Ast.makeNode(CAstNode.OBJECT_REF, receiver, Ast.makeConstant("prototype")));
if (elt.equals("prototype") || elt.equals("__proto__")) {
result = Ast.makeNode(CAstNode.BLOCK_EXPR, get = Ast.makeNode(CAstNode.OBJECT_REF, receiver, Ast.makeConstant(elt)));
} else {
if (context.inAssignment()) {
@ -146,7 +146,7 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
CAstNode.ASSIGN,
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)),
Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)),
Ast.makeConstant("prototype")))),
Ast.makeConstant("__proto__")))),
get = Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)),
Ast.makeConstant(elt)));
}
@ -188,7 +188,7 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
CAstNode.ASSIGN,
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)),
Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)),
Ast.makeConstant("prototype")))),
Ast.makeConstant("__proto__")))),
get = Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)),
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(elementTemp))));