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:
parent
91628b4d1b
commit
201b28eea0
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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))));
|
||||
|
||||
|
|
Loading…
Reference in New Issue