Initial contribution of core script analysis code
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@622 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
5be4678a6e
commit
d8f21f8ee5
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="source"/>
|
||||
<classpathentry kind="src" path="dat"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/js.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/xalan.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1 @@
|
|||
bin
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.ibm.wala.cast.js</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>JavaScript</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
output.js.jar = bin/
|
||||
bin.includes = plugin.xml,\
|
||||
lib/js.jar,\
|
||||
lib/xalan.jar
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
=======================================================================
|
||||
DOMO JavaScript Core build file
|
||||
=======================================================================
|
||||
-->
|
||||
<project name="com.ibm.domo.js" default="jar" basedir=".">
|
||||
|
||||
<!-- Software version details -->
|
||||
<property name="name" value="domojscore" />
|
||||
<property name="module_name" value="com.ibm.domo.js" />
|
||||
<property name="Name" value="DOMO JavaScript Core" />
|
||||
<property name="version" value="1-alpha" />
|
||||
|
||||
<!-- Compilation switches -->
|
||||
<property name="debug" value="true" />
|
||||
<property name="deprecation" value="false" />
|
||||
<property name="optimize" value="true" />
|
||||
<property name="javacFailOnError" value="true" />
|
||||
<property name="javacDebugInfo" value="on" />
|
||||
<property name="javacVerbose" value="false" />
|
||||
|
||||
|
||||
<!-- Set global properties for this build -->
|
||||
<property name="src" value="source" />
|
||||
<property name="dat" value="dat" />
|
||||
<property name="build" value="build" />
|
||||
<property name="build.result" value="${basedir}" />
|
||||
<property name="build.tests" value="${basedir}" />
|
||||
<property name="build.javadocs" value="${build}/javadocs" />
|
||||
<property name="publish.javadocs" value="javadocs/com.ibm.domo.js" />
|
||||
<property name="dist" value="dist" />
|
||||
<property name="etc" value="etc" />
|
||||
<property name="docs" value="docs" />
|
||||
<property name="lib" value="lib" />
|
||||
<property name="mainlib" value="../mainlib" />
|
||||
<property name="sharedlib" value="../sharedlib" />
|
||||
|
||||
<property name="cvsroot" value="/gsa/watgsa/home/d/o/dolby/cvs/JTD"/>
|
||||
|
||||
<import file="${sharedlib}/scripts/common-targets.xml"/>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,102 @@
|
|||
// the internal primitive mechanism
|
||||
primitive = new Primitives();
|
||||
|
||||
// core definitions needed to make anything work, even what follows
|
||||
Object = primitive("NewObject");
|
||||
Function = primitive("NewFunction");
|
||||
Array = primitive("NewArray");
|
||||
String = primitive("NewString");
|
||||
Number = primitive("NewNumber");
|
||||
RegExp = primitive("NewRegExp");
|
||||
|
||||
/************************************************************************/
|
||||
/* Global properties, see spec 15.1 */
|
||||
/************************************************************************/
|
||||
|
||||
undefined = primitive("NewUndefined");
|
||||
|
||||
eval = function eval (x) {
|
||||
return primitive("GlobalEval", x);
|
||||
};
|
||||
|
||||
parseInt = function parseInt (string, radix) {
|
||||
return primitive("GlobalParseInt", string, radix);
|
||||
};
|
||||
|
||||
parseFloat = function parseFloat (string) {
|
||||
return primitive("GlobalParseFloat", string);
|
||||
};
|
||||
|
||||
isNaN = function isNaN (number) {
|
||||
return primitive("GlobalIsNaN", number)
|
||||
};
|
||||
|
||||
isFinite = function isFinite (number) {
|
||||
return primitive("GlobalIsFinite", number);
|
||||
};
|
||||
|
||||
decodeURI = primitive("GlobalDecodeURI");
|
||||
|
||||
decodeURIComponent = primitive("GlobalDecodeURIComponent");
|
||||
|
||||
encodeURI = primitive("GlobalEncodeURI");
|
||||
|
||||
encodeURIComponent = primitive("GlobalEncodeURIComponent");
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Object properties, see spec 15.2 */
|
||||
/************************************************************************/
|
||||
|
||||
Object.prototype = {
|
||||
|
||||
prototype: null,
|
||||
|
||||
constructor: Object,
|
||||
|
||||
toString: function toString() {
|
||||
return primitive("ObjectToString", this);
|
||||
},
|
||||
|
||||
toLocaleString: function toLocaleString() {
|
||||
return primitive("ObjectToLocaleString", this);
|
||||
},
|
||||
|
||||
valueOf: function valueOf() { return this },
|
||||
|
||||
hasOwnProperty: function hasOwnProperty (V) {
|
||||
return primitive("ObjectHasOwnProperty", this, V);
|
||||
},
|
||||
|
||||
isPrototypeOf: function isPrototypeOf (V) {
|
||||
return primitive("ObjectIsPrototypeOf", this, V);
|
||||
},
|
||||
|
||||
propertyIsEnumerable: function propertyIsEnumerable (V) {
|
||||
return primitive("ObjectPropertyIsEnumerable", this, V);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Function properties, see spec 15.3 */
|
||||
/************************************************************************/
|
||||
|
||||
Function.prototype = {
|
||||
|
||||
constructor: Function,
|
||||
|
||||
toString: function functionToString() {
|
||||
return primitive("FunctionToString", this);
|
||||
},
|
||||
|
||||
apply: function functionApply (thisArg, argArray) {
|
||||
return primitive("FunctionApply", this, thisArg, argArray);
|
||||
},
|
||||
|
||||
call: function functionCall (thisArg) {
|
||||
arguments.shift();
|
||||
return primitive("FunctionApply", this, thisArg, arguments);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
// The following stuff has to be statically analyzed
|
||||
// 1. readonly attributes
|
||||
// 2. using setAttribute to register an event handler (this should be disallowed since it can be used like 'eval')
|
||||
// 3. All methods properties assigned here are implicitly readonly
|
||||
// 4. inheritance in this file is implemented by creating a new object for the prototype. Instead, the prototype object could be shared
|
||||
|
||||
// A combination of interfaces NodeList, NamedNodeMap, HTMLCollection
|
||||
function NamedNodeList() {
|
||||
var maxLength = 10;
|
||||
var local = new Array(10);
|
||||
var counter = -1;
|
||||
function add(elem) {
|
||||
checkAndIncrease();
|
||||
local[counter++] = elem;
|
||||
}
|
||||
|
||||
function getIndex(elem) {
|
||||
for(var traverse = 0; traverse <= counter; traverse++) {
|
||||
if(local[traverse] == elem) {
|
||||
return traverse;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function remove(elem) {
|
||||
var found = getIndex(elem);
|
||||
if(found > -1) {
|
||||
for(traverse = found; traverse < counter; traverse++) {
|
||||
local[traverse] = local[traverse+1];
|
||||
}
|
||||
counter--;
|
||||
}
|
||||
}
|
||||
|
||||
function replace(newElem, oldElem) {
|
||||
var found = getIndex(oldElem);
|
||||
if(found > -1) {
|
||||
local[found] = newElem;
|
||||
}
|
||||
}
|
||||
|
||||
function insertBefore(newElem, oldElem) {
|
||||
var found = getIndex(oldElem);
|
||||
if(found > -1) {
|
||||
checkAndIncrease();
|
||||
var prev = newElem;
|
||||
for(var traverse = counter + 1; traverse > found; traverse--) {
|
||||
local[traverse] = local[traverse-1];
|
||||
}
|
||||
local[found] = newElem;
|
||||
}
|
||||
}
|
||||
|
||||
var checkAndIncrease = function() {
|
||||
if(counter >= maxLength - 1) {
|
||||
maxLength += 10;
|
||||
var temp = new Array(maxLength);
|
||||
for(traverse = 0; traverse <= counter; traverse++) {
|
||||
temp[traverse] = local[traverse];
|
||||
}
|
||||
local = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// implement a list of Nodes, accessible through names as well
|
||||
|
||||
}
|
||||
|
||||
function DOMNode() { // An impostor for the Node class
|
||||
this.attributes = new NamedNodeList();
|
||||
this.childNodes = new NamedNodeList();
|
||||
this.insertBefore = function(newChild, refChild) {
|
||||
this.childNodes.insertBefore(newChild, refChild);
|
||||
}
|
||||
this.replaceChild = function(newChild, oldChild) {
|
||||
this.childNodes.replace(newChild, oldChild);
|
||||
}
|
||||
this.removeChild = function(oldChild) {
|
||||
this.childNodes.remove(oldChild);
|
||||
}
|
||||
this.appendChild = function(newChild) {
|
||||
this.childNodes.add(newChild);
|
||||
newChild.parentNode = this;
|
||||
}
|
||||
this.hasChildNodes = function() {
|
||||
return this.childNodes.hasElements();
|
||||
}
|
||||
|
||||
this.ownerDocument = document;
|
||||
}
|
||||
|
||||
function DOMDocument() {
|
||||
this.prototype = new DOMNode();
|
||||
this.createElement = function(name) {
|
||||
// TODO : to be implemented accurately
|
||||
var toReturn = new DOMHTMLGenericElement(name);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
|
||||
function DOMHTMLDocument() {
|
||||
this.prototype = new DOMDocument();
|
||||
this.getElementsByName = function(name) {
|
||||
// get the node in the tree with name attribute == name
|
||||
}
|
||||
}
|
||||
|
||||
// Creating the root document object
|
||||
var document = new DOMHTMLDocument();
|
||||
|
||||
function DOMElement() { // An impostor for the Element class
|
||||
// inherits from Node
|
||||
this.prototype = new DOMNode();
|
||||
|
||||
// The get/set/remove attribute methods cannot be run using 'onclick','onmouseover', 'on...' kind of arguments for name.
|
||||
// since that would be used as a workaround for eval
|
||||
|
||||
this.getAttribute = function(name) {
|
||||
this.attributes.get(name);
|
||||
}
|
||||
this.setAttribute = function(name, value) {
|
||||
this.attributes.set(name, value);
|
||||
}
|
||||
|
||||
this.removeAttribute = function(name) {
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
|
||||
this.getElementsByTagName = function(name) {
|
||||
var toReturn = new NamedNodeList();
|
||||
}
|
||||
}
|
||||
|
||||
function DOMHTMLElement() { // An impostor for the HTMLElement class
|
||||
// inherits from Element
|
||||
this.prototype = new DOMElement();
|
||||
|
||||
// Set HTML Attribute Defaults
|
||||
this.id = null;
|
||||
this.title = null;
|
||||
this.lang = null;
|
||||
this.dir = null;
|
||||
this.className = null;
|
||||
|
||||
// Set Javascript properties
|
||||
this.getAttribute = function(name) {
|
||||
if(name == "id") return this.id;
|
||||
else if(name == "title") return this.title;
|
||||
else if(name == "lang") return this.lang;
|
||||
else if(name == "dir") return this.dir;
|
||||
else if(name == "class") return this.className;
|
||||
else return this.attributes.get(name);
|
||||
}
|
||||
|
||||
this.setAttribute = function(name, value) {
|
||||
if(name == "id") this.id = value;
|
||||
else if(name == "title") this.title = value;
|
||||
else if(name == "lang") this.lang = value;
|
||||
else if(name == "dir") this.dir = value;
|
||||
else if(name == "class") this.className = value;
|
||||
else return this.attributes.set(name, value);
|
||||
}
|
||||
|
||||
this.removeAttribute = function(name) {
|
||||
if(name == "id") this.id = null;
|
||||
else if(name == "title") this.title = null;
|
||||
else if(name == "lang") this.lang = null;
|
||||
else if(name == "dir") this.dir = null;
|
||||
else if(name == "class") this.className = null;
|
||||
else return this.attributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Just a hack until all HTML elements have corresponding constructors
|
||||
function DOMHTMLGenericElement(tagName) {
|
||||
// inherits from Element
|
||||
this.prototype = new DOMElement();
|
||||
|
||||
// Set just the tag name
|
||||
this.nodeName = tagName;
|
||||
this.nodeValue = null;
|
||||
}
|
||||
|
||||
function DOMHTMLFormElement() {
|
||||
// inherits from HTMLElement
|
||||
this.prototype = new DOMHTMLElement();
|
||||
|
||||
// Set Javascript properties
|
||||
this.nodeName = "FORM";
|
||||
this.elements = new NamedNodeList();
|
||||
this.length = function() {
|
||||
return this.elements.length;
|
||||
}
|
||||
this.submit = function() {
|
||||
}
|
||||
this.reset = function() {
|
||||
}
|
||||
|
||||
// Set HTML Attribute Defaults
|
||||
this.name = null;
|
||||
this.acceptCharset = "UNKNOWN";
|
||||
this.action = null;
|
||||
this.enctype = "application/x-www-form-urlencoded";
|
||||
this.method = "get";
|
||||
this.target = null;
|
||||
|
||||
// Set Javascript properties
|
||||
this.getAttribute = function(name) {
|
||||
if(name == "name") return this.name;
|
||||
else if(name == "accept-charset") return this.acceptCharset;
|
||||
else if(name == "action") return this.action;
|
||||
else if(name == "enctype") return this.enctype;
|
||||
else if(name == "method") return this.method;
|
||||
else if(name == "target") return this.target;
|
||||
else return this.prototype.getAttribute(name);
|
||||
}
|
||||
|
||||
this.setAttribute = function(name, value) {
|
||||
if(name == "name") this.name = value;
|
||||
else if(name == "accept-charset") this.acceptCharset = value;
|
||||
else if(name == "action") this.action = value;
|
||||
else if(name == "enctype") this.enctype = value;
|
||||
else if(name == "method") this.method = value;
|
||||
else if(name == "target") this.target = value;
|
||||
else return this.prototype.setAttribute(name, value);
|
||||
}
|
||||
|
||||
this.removeAttribute = function(name) {
|
||||
if(name == "name") this.name = null;
|
||||
else if(name == "accept-charset") this.acceptCharset = null;
|
||||
else if(name == "action") this.action = null;
|
||||
else if(name == "enctype") this.enctype = null;
|
||||
else if(name == "method") this.method = null;
|
||||
else if(name == "target") this.target = null;
|
||||
else return this.prototype.removeAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
function DOMHTMLTableElement () {
|
||||
// inherits from HTMLElement
|
||||
this.prototype = new DOMHTMLElement();
|
||||
|
||||
this.rows = function() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,389 @@
|
|||
// the internal primitive mechanism
|
||||
primitive = new Primitives();
|
||||
|
||||
// core definitions needed to make anything work, even what follows
|
||||
Object = primitive("NewObject");
|
||||
Function = primitive("NewFunction");
|
||||
Array = primitive("NewArray");
|
||||
String = primitive("NewString");
|
||||
Number = primitive("NewNumber");
|
||||
RegExp = primitive("NewRegExp");
|
||||
|
||||
/************************************************************************/
|
||||
/* Global properties, see spec 15.1 */
|
||||
/************************************************************************/
|
||||
NaN = primitive("GlobalNaN");
|
||||
|
||||
Infinity = primitive("GlobalInfinity");
|
||||
|
||||
undefined = primitive("NewUndefined");
|
||||
|
||||
eval = function eval (x) {
|
||||
return primitive("GlobalEval", x);
|
||||
};
|
||||
|
||||
parseInt = function parseInt (string, radix) {
|
||||
return primitive("GlobalParseInt", string, radix);
|
||||
};
|
||||
|
||||
parseFloat = function parseFloat (string) {
|
||||
return primitive("GlobalParseFloat", string);
|
||||
};
|
||||
|
||||
isNaN = function isNaN (number) {
|
||||
return primitive("GlobalIsNaN", number)
|
||||
};
|
||||
|
||||
isFinite = function isFinite (number) {
|
||||
return primitive("GlobalIsFinite", number);
|
||||
};
|
||||
|
||||
decodeURI = primitive("GlobalDecodeURI");
|
||||
|
||||
decodeURIComponent = primitive("GlobalDecodeURIComponent");
|
||||
|
||||
encodeURI = primitive("GlobalEncodeURI");
|
||||
|
||||
encodeURIComponent = primitive("GlobalEncodeURIComponent");
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Object properties, see spec 15.2 */
|
||||
/************************************************************************/
|
||||
|
||||
Object.prototype = {
|
||||
|
||||
prototype: null,
|
||||
|
||||
constructor: Object,
|
||||
|
||||
toString: function toString() {
|
||||
return primitive("ObjectToString", this);
|
||||
},
|
||||
|
||||
toLocaleString: function toLocaleString() {
|
||||
return primitive("ObjectToLocaleString", this);
|
||||
},
|
||||
|
||||
valueOf: function valueOf() { return this },
|
||||
|
||||
hasOwnProperty: function hasOwnProperty (V) {
|
||||
return primitive("ObjectHasOwnProperty", this, V);
|
||||
},
|
||||
|
||||
isPrototypeOf: function isPrototypeOf (V) {
|
||||
return primitive("ObjectIsPrototypeOf", this, V);
|
||||
},
|
||||
|
||||
propertyIsEnumerable: function propertyIsEnumerable (V) {
|
||||
return primitive("ObjectPropertyIsEnumerable", this, V);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Function properties, see spec 15.3 */
|
||||
/************************************************************************/
|
||||
|
||||
Function.prototype = {
|
||||
|
||||
constructor: Function,
|
||||
|
||||
toString: function functionToString() {
|
||||
return primitive("FunctionToString", this);
|
||||
},
|
||||
|
||||
apply: function functionApply (thisArg, argArray) {
|
||||
return primitive("FunctionApply", this, thisArg, argArray);
|
||||
},
|
||||
|
||||
call: function functionCall (thisArg) {
|
||||
arguments.shift();
|
||||
return primitive("FunctionApply", this, thisArg, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Array properties, see spec 15.4 */
|
||||
/************************************************************************/
|
||||
|
||||
Array.prototype = {
|
||||
|
||||
prototype: Object.prototype,
|
||||
|
||||
constructor: Array,
|
||||
|
||||
toString: function arrayToString () {
|
||||
return this.join(",");
|
||||
},
|
||||
|
||||
toLocaleString: function arrayToLocalString () {
|
||||
var result = "";
|
||||
var limit = this.length;
|
||||
for(var k = 0; k < limit; k++) {
|
||||
result = result.concat( this[k].toLocaleString() );
|
||||
result = result.concat( "," );
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
concat: function concat () {
|
||||
var result = new Array();
|
||||
var n = 0;
|
||||
|
||||
for(var i = 0; i < this.length; i++)
|
||||
result[n++] = this[i];
|
||||
|
||||
for(i = 0; i < arguments.length; i++)
|
||||
for(var j = 0; j < arguments[i].length; j++)
|
||||
result[n++] = arguments[i][j];
|
||||
|
||||
result.length = n;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
join: function join (separator) {
|
||||
var result = "";
|
||||
var limit = this.length;
|
||||
for(var k = 0; k < limit; k++) {
|
||||
result = result.concat( this[k].toString() );
|
||||
result = result.concat( separator );
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
pop: function pop () {
|
||||
return this[ --this.length ];
|
||||
},
|
||||
|
||||
push: function push () {
|
||||
var n = this.length
|
||||
for(var i = 0; i < arguments.length; i++) {
|
||||
this[ n++ ] = arguments[i];
|
||||
}
|
||||
|
||||
this.length = n;
|
||||
return n;
|
||||
},
|
||||
|
||||
reverse: function reverse () {
|
||||
var n = this.length;
|
||||
for (var k = 0; k < (n/2); k++) {
|
||||
var tmp = this[k];
|
||||
this[k] = this[n-k];
|
||||
this[n-k] = tmp;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
shift: function shift () {
|
||||
var result = this[ 0 ];
|
||||
for(var i = 0; i < this.length-1; i++)
|
||||
this[i] = this[i+1];
|
||||
|
||||
this.length--;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
slice: function slice (start, end) {
|
||||
var j = 0;
|
||||
if (start < 0) start = this.length + start;
|
||||
if (end < 0) end = this.length + end;
|
||||
var result = new Array();
|
||||
for(var i = start; i < end; i++)
|
||||
result[j++] = this[i];
|
||||
|
||||
result.length = j;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
sort: function sort (fn) {
|
||||
for(var l = 0; i < this.length; l++) {
|
||||
var mindex = l;
|
||||
for(var i = l; i < this.length; i++) {
|
||||
if (fn(this[mindex], this[i]) < 0) {
|
||||
mindex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (mindex != l) {
|
||||
var tmp = this[l];
|
||||
this[l] = this[mindex];
|
||||
this[mindex] = this[l];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* String properties, see spec 15.4 */
|
||||
/************************************************************************/
|
||||
|
||||
String.prototype = {
|
||||
|
||||
prototype: Object.prototype,
|
||||
|
||||
constructor: String,
|
||||
|
||||
$value: "",
|
||||
|
||||
toString: function stringToString() {
|
||||
return this.$value;
|
||||
},
|
||||
|
||||
valueOf: function stringValueOf() {
|
||||
return this.$value;
|
||||
},
|
||||
|
||||
charAt: function stringCharAt(pos) {
|
||||
return new String(primitive("StringCharAt", pos));
|
||||
},
|
||||
|
||||
charCodeAt: function stringCharCodeAt(pos) {
|
||||
return new Number(primitive("StringCharCodeAt", pos));
|
||||
},
|
||||
|
||||
toUpperCase: function toUpperCase() {
|
||||
return new String(primitive("StringToUpperCase", this));
|
||||
},
|
||||
|
||||
toLocaleUpperCase: function toLocaleUpperCase() {
|
||||
return new String(primitive("StringToLocaleUpperCase", this));
|
||||
},
|
||||
|
||||
toLowerCase: function toLowerCase() {
|
||||
return new String(primitive("StringToLowerCase", this));
|
||||
},
|
||||
|
||||
toLocaleLowerCase: function toLocaleLowerCase() {
|
||||
return new String(primitive("StringToLocaleLowerCase", this));
|
||||
},
|
||||
|
||||
indexOf: function indexOf(str) {
|
||||
return new Number(primitive("StringIndexOf", this, str));
|
||||
},
|
||||
|
||||
split: function stringSplit(separator, limit) {
|
||||
var y = primitive("splitCount", this, separator, limit);
|
||||
var x = new Array(y);
|
||||
for(var i = 0; i < y; i++) {
|
||||
x[i] = new String( primitive("splitNth", this, separator, limit, i) );
|
||||
}
|
||||
return x;
|
||||
},
|
||||
|
||||
substring: function substring(from, to) {
|
||||
return new String(primitive("StringSubString", this, from, to));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Number properties, see spec 15.7 */
|
||||
/************************************************************************/
|
||||
|
||||
Number.prototype = {
|
||||
|
||||
prototype: Object.prototype,
|
||||
|
||||
constructor: Number,
|
||||
|
||||
$value: 0
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Math properties, see spec 15.8 */
|
||||
/************************************************************************/
|
||||
Math = {
|
||||
|
||||
E: primitive("MathE"),
|
||||
|
||||
LN10: primitive("MathLN10"),
|
||||
|
||||
LN2: primitive("MathLN2"),
|
||||
|
||||
LOG2E: primitive("MathLOG2E"),
|
||||
|
||||
LOG10E: primitive("MathLOG10E"),
|
||||
|
||||
PI: primitive("PI"),
|
||||
|
||||
SQRT1_2: primitive("MathSQRT1_2"),
|
||||
|
||||
SQRT2: primitive("MathSQRT2"),
|
||||
|
||||
abs: function abs (x) { return (x<0)? -x: x; },
|
||||
|
||||
acos: function acos (x) { return primitive("MathACos", x); },
|
||||
|
||||
asin: function asin (x) { return primitive("MathASin", x); },
|
||||
|
||||
atan: function atan (x) { return primitive("MathATan", x); },
|
||||
|
||||
atan2: function atan2 (y, x) { return primitive("MathATan2", y, x); },
|
||||
|
||||
ceil: function ceil (x) { return primitive("MathCeil", x); },
|
||||
|
||||
cos: function cos (x) { return primitive("MathCos", x); },
|
||||
|
||||
exp: function exp (x) { return primitive("MathExp", x); },
|
||||
|
||||
floor: function floor (x) { return primitive("MathFloor", x); },
|
||||
|
||||
log: function log (x) { return primitive("MathLog", x); },
|
||||
|
||||
max: function max () {
|
||||
var i = -Infinity;
|
||||
for(var j = 0; j < arguments.length; j++)
|
||||
if (arguments[j] > i)
|
||||
i = arguments[j];
|
||||
|
||||
return i;
|
||||
},
|
||||
|
||||
min: function min () {
|
||||
var i = Infinity;
|
||||
for(var j = 0; j < arguments.length; j++)
|
||||
if (arguments[j] < i)
|
||||
i = arguments[j];
|
||||
|
||||
return i;
|
||||
},
|
||||
|
||||
pow: function pow (x, y) { return primitive("MathPow", x, y); },
|
||||
|
||||
random: function random() { return primitive("MathRandom"); },
|
||||
|
||||
round: function round (x) { return primitive("MathRound", x); },
|
||||
|
||||
sin: function sin (x) { return primitive("MathSin", x); },
|
||||
|
||||
sqrt: function sqrt (x) { return primitive("MathSqrt", x);},
|
||||
|
||||
tan: function tan (x) { return primitive("MathTan", x); }
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* RegExp properties, see spec 15.10 */
|
||||
/************************************************************************/
|
||||
|
||||
RegExp.prototype = {
|
||||
|
||||
prototype: Object.prototype,
|
||||
|
||||
constructor: RegExp
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.0"?>
|
||||
<plugin
|
||||
id="com.ibm.domo.js"
|
||||
name="JavaScript Plug-in"
|
||||
version="1.0.0"
|
||||
provider-name="IBM"
|
||||
class="com.ibm.wala.cast.js.JavaScriptPlugin">
|
||||
|
||||
<runtime>
|
||||
<library name="lib/js.jar">
|
||||
<export name="*"/>
|
||||
</library>
|
||||
<library name="lib/xalan.jar">
|
||||
<export name="*"/>
|
||||
</library>
|
||||
</runtime>
|
||||
|
||||
<requires>
|
||||
<import plugin="org.eclipse.core.runtime"/>
|
||||
<import plugin="com.ibm.wala.cast"/>
|
||||
<import plugin="com.ibm.wala.core"/>
|
||||
</requires>
|
||||
|
||||
</plugin>
|
|
@ -0,0 +1,85 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* The main plugin class to be used in the desktop.
|
||||
*/
|
||||
public class JavaScriptPlugin extends Plugin {
|
||||
//The shared instance.
|
||||
private static JavaScriptPlugin plugin;
|
||||
//Resource bundle.
|
||||
private ResourceBundle resourceBundle;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public JavaScriptPlugin() {
|
||||
super();
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called upon plug-in activation
|
||||
*/
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the plug-in is stopped
|
||||
*/
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
super.stop(context);
|
||||
plugin = null;
|
||||
resourceBundle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared instance.
|
||||
*/
|
||||
public static JavaScriptPlugin getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string from the plugin's resource bundle,
|
||||
* or 'key' if not found.
|
||||
*/
|
||||
public static String getResourceString(String key) {
|
||||
ResourceBundle bundle = JavaScriptPlugin.getDefault().getResourceBundle();
|
||||
try {
|
||||
return (bundle != null) ? bundle.getString(key) : key;
|
||||
} catch (MissingResourceException e) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin's resource bundle,
|
||||
*/
|
||||
public ResourceBundle getResourceBundle() {
|
||||
try {
|
||||
if (resourceBundle == null)
|
||||
resourceBundle = ResourceBundle.getBundle("com.ibm.domo.js.JavaScriptPluginResources");
|
||||
} catch (MissingResourceException x) {
|
||||
resourceBundle = null;
|
||||
}
|
||||
return resourceBundle;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.analysis.typeInference;
|
||||
|
||||
import com.ibm.wala.fixpoint.IVariable;
|
||||
import com.ibm.wala.analysis.typeInference.*;
|
||||
import com.ibm.wala.cast.analysis.typeInference.AstTypeInference;
|
||||
import com.ibm.wala.cast.js.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class JSTypeInference extends AstTypeInference {
|
||||
|
||||
public JSTypeInference(IR ir, ClassHierarchy cha) {
|
||||
super(ir, cha, true);
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
class JSTypeOperatorFactory
|
||||
extends AstTypeOperatorFactory
|
||||
implements com.ibm.wala.cast.js.ssa.InstructionVisitor
|
||||
{
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
|
||||
result = new DeclaredTypeOperator(new ConeType(cha.getRootClass(), cha));
|
||||
}
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead inst) {
|
||||
result = new DeclaredTypeOperator(new ConeType(cha.getRootClass(), cha));
|
||||
}
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
|
||||
result = new DeclaredTypeOperator(new PointType(cha.lookupClass(JavaScriptTypes.String), cha));
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite inst) {
|
||||
}
|
||||
};
|
||||
|
||||
class JSTypeVarFactory extends TypeVarFactory {
|
||||
|
||||
private TypeAbstraction make(TypeReference typeRef) {
|
||||
return new PointType(cha.lookupClass( typeRef ), cha);
|
||||
}
|
||||
|
||||
public IVariable makeVariable(int vn) {
|
||||
if (ir.getSymbolTable().isStringConstant( vn )) {
|
||||
return new TypeVariable(make(JavaScriptTypes.String), 1331*vn);
|
||||
} else if (ir.getSymbolTable().isNumberConstant( vn )) {
|
||||
return new TypeVariable(make(JavaScriptTypes.Number), 797*vn);
|
||||
} else if (ir.getSymbolTable().isNullConstant( vn )) {
|
||||
return new TypeVariable(make(JavaScriptTypes.Null), 4077*vn);
|
||||
} else {
|
||||
return super.makeVariable( vn );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
init(ir, new JSTypeVarFactory(), new JSTypeOperatorFactory());
|
||||
}
|
||||
|
||||
public TypeAbstraction getConstantType(int valueNumber) {
|
||||
SymbolTable st = ir.getSymbolTable();
|
||||
if (st.isStringConstant(valueNumber)) {
|
||||
return new PointType(cha.lookupClass(JavaScriptTypes.String), cha);
|
||||
} else if (st.isNullConstant(valueNumber)) {
|
||||
return new PointType(cha.lookupClass(JavaScriptTypes.Null), cha);
|
||||
} else {
|
||||
return new PointType(cha.lookupClass(JavaScriptTypes.Number), cha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.cfg;
|
||||
|
||||
import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
|
||||
import com.ibm.wala.cast.js.ssa.*;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
|
||||
public class JSInducedCFG extends AstInducedCFG {
|
||||
|
||||
public JSInducedCFG(SSAInstruction[] instructions, IMethod method, Context context) {
|
||||
super(instructions, method, context);
|
||||
}
|
||||
|
||||
class JSPEIVisitor extends AstPEIVisitor implements InstructionVisitor {
|
||||
|
||||
JSPEIVisitor(boolean[] r) {
|
||||
super(r);
|
||||
}
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead inst) {
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite inst) {
|
||||
}
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
|
||||
}
|
||||
}
|
||||
|
||||
class JSBranchVisitor extends AstBranchVisitor implements InstructionVisitor {
|
||||
|
||||
JSBranchVisitor(boolean[] r) {
|
||||
super(r);
|
||||
}
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead inst) {
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite inst) {
|
||||
}
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
|
||||
}
|
||||
}
|
||||
|
||||
protected BranchVisitor makeBranchVisitor(boolean[] r) {
|
||||
return new JSBranchVisitor(r);
|
||||
}
|
||||
|
||||
protected PEIVisitor makePEIVisitor(boolean[] r) {
|
||||
return new JSPEIVisitor(r);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.client;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.cast.js.client.impl.*;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.js.loader.*;
|
||||
import com.ibm.wala.cast.js.translator.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.client.*;
|
||||
import com.ibm.wala.client.impl.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.jar.*;
|
||||
|
||||
public class JavaScriptAnalysisEngine extends AbstractAnalysisEngine {
|
||||
|
||||
protected JavaScriptLoaderFactory loaderFactory;
|
||||
|
||||
protected JavaScriptTranslatorFactory translatorFactory;
|
||||
|
||||
protected boolean keepIRs = true;
|
||||
|
||||
public JavaScriptAnalysisEngine() {
|
||||
setCallGraphBuilderFactory(
|
||||
new com.ibm.wala.cast.js.client.impl.ZeroCFABuilderFactory() );
|
||||
}
|
||||
|
||||
protected void buildAnalysisScope() {
|
||||
try {
|
||||
loaderFactory = new JavaScriptLoaderFactory(translatorFactory);
|
||||
|
||||
SourceFileModule[] files = (SourceFileModule[])
|
||||
moduleFiles.toArray(new SourceFileModule[ moduleFiles.size() ]);
|
||||
|
||||
scope = new CAstAnalysisScope( files, loaderFactory );
|
||||
} catch (IOException e) {
|
||||
Assertions.UNREACHABLE(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected ClassHierarchy buildClassHierarchy() {
|
||||
try {
|
||||
return
|
||||
ClassHierarchy.make(
|
||||
getScope(), loaderFactory, getWarnings(), JavaScriptTypes.Root);
|
||||
} catch (ClassHierarchyException e) {
|
||||
Assertions.UNREACHABLE(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTranslatorFactory(JavaScriptTranslatorFactory factory) {
|
||||
this.translatorFactory = factory;
|
||||
}
|
||||
|
||||
public void setJ2SELibraries(JarFile[] libs) {
|
||||
Assertions.UNREACHABLE("Illegal to call setJ2SELibraries");
|
||||
}
|
||||
|
||||
public void setJ2SELibraries(Module[] libs) {
|
||||
Assertions.UNREACHABLE("Illegal to call setJ2SELibraries");
|
||||
}
|
||||
|
||||
public AnalysisOptions getDefaultOptions(Entrypoints roots) {
|
||||
final AnalysisOptions options =
|
||||
new AnalysisOptions(
|
||||
scope,
|
||||
AstIRFactory.makeDefaultFactory(keepIRs),
|
||||
roots);
|
||||
|
||||
options.setConstantType(String.class, JavaScriptTypes.String);
|
||||
options.setConstantType(Integer.class, JavaScriptTypes.Number);
|
||||
options.setConstantType(Float.class, JavaScriptTypes.Number);
|
||||
options.setConstantType(Double.class, JavaScriptTypes.Number);
|
||||
options.setConstantType(null, JavaScriptTypes.Null);
|
||||
|
||||
options.setUseConstantSpecificKeys( true );
|
||||
|
||||
options.setUseStacksForLexicalScoping( true );
|
||||
|
||||
options.getSSAOptions().setPreserveNames( true );
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.client.impl;
|
||||
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.*;
|
||||
import com.ibm.wala.client.CallGraphBuilderFactory;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.*;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*
|
||||
* A factory to create call graph builders using 0-CFA
|
||||
*/
|
||||
public class ZeroCFABuilderFactory implements CallGraphBuilderFactory {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.domo.j2ee.client.CallGraphBuilderFactory#make(com.ibm.domo.ipa.callgraph.AnalysisOptions,
|
||||
* com.ibm.domo.ipa.cha.ClassHierarchy, java.lang.ClassLoader,
|
||||
* com.ibm.domo.j2ee.J2EEAnalysisScope,
|
||||
* com.ibm.domo.util.warnings.WarningSet, boolean)
|
||||
*/
|
||||
public CallGraphBuilder make(AnalysisOptions options,
|
||||
ClassHierarchy cha,
|
||||
AnalysisScope scope,
|
||||
WarningSet warnings,
|
||||
boolean keepPointsTo)
|
||||
{
|
||||
com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha, warnings);
|
||||
options.setSelector(new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector()));
|
||||
|
||||
return new JSZeroXCFABuilder(cha, warnings, options, null, null, null, ZeroXInstanceKeys.NONE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* Common utilities for CFA-style call graph builders.
|
||||
*/
|
||||
public class JSCFABuilder extends JSSSAPropagationCallGraphBuilder {
|
||||
|
||||
/**
|
||||
* @param cha
|
||||
* @param warnings
|
||||
*/
|
||||
public JSCFABuilder(ClassHierarchy cha, WarningSet warnings, AnalysisOptions options) {
|
||||
super(cha, warnings, options, new AstCFAPointerKeys());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.js.cfg.*;
|
||||
import com.ibm.wala.cast.js.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cfg.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.impl.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
public class JSCallGraph extends AstCallGraph {
|
||||
|
||||
public JSCallGraph(ClassHierarchy cha, AnalysisOptions options, WarningSet warnings) {
|
||||
super(cha, options, warnings);
|
||||
}
|
||||
|
||||
public class JSFakeRoot extends ScriptFakeRoot {
|
||||
|
||||
public JSFakeRoot(ClassHierarchy cha, AnalysisOptions options) {
|
||||
super(cha, options);
|
||||
}
|
||||
|
||||
public InducedCFG makeControlFlowGraph() {
|
||||
return new JSInducedCFG(getStatements(new WarningSet()), this, Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
public SSANewInstruction addAllocation(TypeReference T, WarningSet warnings) {
|
||||
if (cha.isSubclassOf(cha.lookupClass(T), cha.lookupClass(JavaScriptTypes.Root))) {
|
||||
int instance = nextLocal++;
|
||||
NewSiteReference ref = NewSiteReference.make(statements.size(), T);
|
||||
SSANewInstruction result = new JavaScriptNewInstruction(instance, ref);
|
||||
statements.add(result);
|
||||
return result;
|
||||
} else {
|
||||
return super.addAllocation(T, warnings);
|
||||
}
|
||||
}
|
||||
|
||||
public SSAAbstractInvokeInstruction addDirectCall(int function,
|
||||
int[] params,
|
||||
CallSiteReference site)
|
||||
{
|
||||
CallSiteReference newSite = CallSiteReference.make(statements.size(), site.getDeclaredTarget(), site.getInvocationCode());
|
||||
|
||||
JavaScriptInvoke s =
|
||||
new JavaScriptInvoke(function, nextLocal++, params, nextLocal++, newSite);
|
||||
statements.add(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
protected CGNode makeFakeRootNode() {
|
||||
return findOrCreateNode(new JSFakeRoot(cha, options), Everywhere.EVERYWHERE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,612 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.fixpoint.IVariable;
|
||||
import com.ibm.wala.fixedpoint.impl.*;
|
||||
import com.ibm.wala.util.intset.*;
|
||||
import com.ibm.wala.analysis.typeInference.TypeInference;
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.ir.ssa.EachElementHasNextInstruction;
|
||||
import com.ibm.wala.cast.js.analysis.typeInference.JSTypeInference;
|
||||
import com.ibm.wala.cast.js.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.fixpoint.IntSetVariable;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.*;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.ssa.SSACFG.BasicBlock;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder {
|
||||
|
||||
public static final boolean DEBUG_LEXICAL = false;
|
||||
public static final boolean DEBUG_TYPE_INFERENCE = false;
|
||||
|
||||
protected
|
||||
JSSSAPropagationCallGraphBuilder(ClassHierarchy cha,
|
||||
WarningSet warnings,
|
||||
AnalysisOptions options,
|
||||
PointerKeyFactory pointerKeyFactory)
|
||||
{
|
||||
super(cha, warnings, options, pointerKeyFactory);
|
||||
}
|
||||
|
||||
protected boolean isConstantRef(SymbolTable symbolTable, int valueNumber) {
|
||||
if (valueNumber == -1) {
|
||||
return false;
|
||||
}
|
||||
return symbolTable.isConstant(valueNumber);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// language specialization interface
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected boolean useObjectCatalog() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// top-level node constraint generation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected ExplicitCallGraph createEmptyCallGraph(ClassHierarchy cha, AnalysisOptions options) {
|
||||
return new JSCallGraph(cha, options, getWarnings());
|
||||
}
|
||||
|
||||
protected TypeInference makeTypeInference(IR ir, ClassHierarchy cha) {
|
||||
TypeInference ti = new JSTypeInference(ir, cha);
|
||||
ti.solve();
|
||||
|
||||
if (DEBUG_TYPE_INFERENCE) {
|
||||
Trace.println("IR of " + ir.getMethod());
|
||||
Trace.println( ir );
|
||||
Trace.println("TypeInference of " + ir.getMethod());
|
||||
for(int i = 0; i < ir.getSymbolTable().getMaxValueNumber(); i++) {
|
||||
if (ti.isUndefined(i)) {
|
||||
Trace.println(" value " + i + " is undefined");
|
||||
} else {
|
||||
Trace.println(" value " + i + " has type " + ti.getType(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ti;
|
||||
}
|
||||
|
||||
protected void addAssignmentsForCatchPointerKey(PointerKey exceptionVar, Set catchClasses, PointerKey e) {
|
||||
system.newConstraint(exceptionVar, assignOperator, e);
|
||||
}
|
||||
|
||||
class JSInterestingVisitor
|
||||
extends AstInterestingVisitor
|
||||
implements com.ibm.wala.cast.js.ssa.InstructionVisitor
|
||||
{
|
||||
JSInterestingVisitor(int vn) {
|
||||
super(vn);
|
||||
}
|
||||
|
||||
public void visitBinaryOp(final SSABinaryOpInstruction instruction) {
|
||||
bingo = true;
|
||||
}
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
|
||||
bingo = true;
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
|
||||
bingo = true;
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
|
||||
bingo = true;
|
||||
}
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
|
||||
bingo = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected InterestingVisitor makeInterestingVisitor(int vn) {
|
||||
return new JSInterestingVisitor(vn);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// specialized pointer analysis
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected class JSPointerFlowGraph extends AstPointerFlowGraph {
|
||||
|
||||
protected class JSPointerFlowVisitor
|
||||
extends AstPointerFlowVisitor
|
||||
implements com.ibm.wala.cast.js.ssa.InstructionVisitor
|
||||
{
|
||||
protected JSPointerFlowVisitor(CGNode node, IR ir, BasicBlock bb) {
|
||||
super(node, ir, bb);
|
||||
}
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
|
||||
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
|
||||
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
|
||||
|
||||
}
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction instruction) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected JSPointerFlowGraph(PointerAnalysis pa, CallGraph cg) {
|
||||
super(pa,cg);
|
||||
}
|
||||
|
||||
protected InstructionVisitor makeInstructionVisitor(CGNode node, IR ir, BasicBlock bb) {
|
||||
return new JSPointerFlowVisitor(node,ir, bb);
|
||||
}
|
||||
}
|
||||
|
||||
public PointerFlowGraphFactory getPointerFlowGraphFactory() {
|
||||
return new PointerFlowGraphFactory() {
|
||||
public PointerFlowGraph make(PointerAnalysis pa, CallGraph cg) {
|
||||
return new JSPointerFlowGraph(pa, cg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// function call handling
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class JSDispatchOperator extends UnaryOperator {
|
||||
private final JavaScriptInvoke call;
|
||||
private final ExplicitCallGraph.ExplicitNode node;
|
||||
private final InstanceKey[][] constParams;
|
||||
private final PointerKey uniqueCatch;
|
||||
|
||||
public boolean isLoadOperator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "JSDispatch of " + call.getCallSite();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return call.getCallSite().hashCode() * node.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof JSDispatchOperator) &&
|
||||
((JSDispatchOperator)o).node.equals(node) &&
|
||||
((JSDispatchOperator)o).call.equals(call);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param call
|
||||
* @param node
|
||||
*/
|
||||
JSDispatchOperator(JavaScriptInvoke call, ExplicitCallGraph.ExplicitNode node, InstanceKey[][] constParams, PointerKey uniqueCatch) {
|
||||
this.call = call;
|
||||
this.node = node;
|
||||
this.constParams = constParams;
|
||||
this.uniqueCatch = uniqueCatch;
|
||||
}
|
||||
|
||||
private MutableIntSet previousReceivers = IntSetUtil.getDefaultIntSetFactory().make();
|
||||
|
||||
public byte evaluate(IVariable lhs, IVariable rhs) {
|
||||
final IntSetVariable receivers = (IntSetVariable) rhs;
|
||||
if (receivers.getValue() != null) {
|
||||
receivers.getValue().foreachExcluding(
|
||||
previousReceivers,
|
||||
new IntSetAction() {
|
||||
public void act(int ptr) {
|
||||
InstanceKey iKey = system.getInstanceKey(ptr);
|
||||
CGNode target = getTargetForCall(node, call.getSite(), iKey);
|
||||
if (target != null) {
|
||||
processJSCall(node, call, target, iKey, constParams, uniqueCatch);
|
||||
if (!haveAlreadyVisited(target)) {
|
||||
markDiscovered(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
previousReceivers.addAll( receivers.getValue() );
|
||||
}
|
||||
|
||||
return NOT_CHANGED;
|
||||
};
|
||||
}
|
||||
|
||||
void processJSCall(CGNode caller,
|
||||
JavaScriptInvoke instruction,
|
||||
CGNode target,
|
||||
InstanceKey function,
|
||||
InstanceKey constParams[][],
|
||||
PointerKey uniqueCatchKey)
|
||||
{
|
||||
caller.addTarget(instruction.getCallSite(), target);
|
||||
if (!haveAlreadyVisited(target)) {
|
||||
markDiscovered(target);
|
||||
}
|
||||
|
||||
IR sourceIR = getCFAContextInterpreter().getIR(caller, getWarnings());
|
||||
SymbolTable sourceST = sourceIR.getSymbolTable();
|
||||
|
||||
IR targetIR = getCFAContextInterpreter().getIR(target, getWarnings());
|
||||
SymbolTable targetST = targetIR.getSymbolTable();
|
||||
|
||||
int av = -1;
|
||||
for(int v = 0; v < targetST.getMaxValueNumber(); v++) {
|
||||
String[] vns = targetIR.getLocalNames(1, v);
|
||||
for(int n = 0; vns != null && n < vns.length; n++) {
|
||||
if ("arguments".equals( vns[n] )) {
|
||||
av = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int paramCount = targetST.getParameterValueNumbers().length;
|
||||
int argCount = instruction.getNumberOfParameters();
|
||||
|
||||
// pass actual arguments to formals in the normal way
|
||||
for(int i = 0; i < Math.min(paramCount, argCount); i++) {
|
||||
int fn = targetST.getConstant(i);
|
||||
PointerKey F =
|
||||
(i == 0)?
|
||||
getFilteredPointerKeyForLocal(
|
||||
target,
|
||||
targetST.getParameter(i),
|
||||
function):
|
||||
getPointerKeyForLocal(target, targetST.getParameter(i));
|
||||
|
||||
if (constParams != null && constParams[i] != null) {
|
||||
for(int j = 0; j < constParams[i].length; j++) {
|
||||
system.newConstraint(F, constParams[i][j]);
|
||||
}
|
||||
|
||||
if (av != -1) newFieldWrite(target, av, fn, constParams[i]);
|
||||
|
||||
} else {
|
||||
PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i));
|
||||
system.newConstraint(
|
||||
F,
|
||||
(F instanceof FilteredPointerKey)?
|
||||
(UnaryOperator)filterOperator:
|
||||
(UnaryOperator)assignOperator,
|
||||
A);
|
||||
|
||||
if (av != -1) newFieldWrite(target, av, fn, F);
|
||||
}
|
||||
}
|
||||
|
||||
// extra actual arguments get assigned into the ``arguments'' object
|
||||
if (paramCount < argCount) {
|
||||
if (av != -1) {
|
||||
for(int i = paramCount; i < argCount; i++) {
|
||||
int fn = targetST.getConstant(i);
|
||||
if (constParams != null && constParams[i] != null) {
|
||||
newFieldWrite(target, av, fn, constParams[i]);
|
||||
} else {
|
||||
PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i));
|
||||
newFieldWrite(target, av, fn, A);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extra formal parameters get null (extra args are ignored here)
|
||||
else if (argCount < paramCount) {
|
||||
int nullvn = sourceST.getNullConstant();
|
||||
DefUse sourceDU = getCFAContextInterpreter().getDU(caller, getWarnings());
|
||||
InstanceKey[] nullkeys = getInvariantContents(sourceST, sourceDU, caller, nullvn, this);
|
||||
for(int i = argCount; i < paramCount; i++) {
|
||||
PointerKey F = getPointerKeyForLocal(target, targetST.getParameter(i));
|
||||
for(int k = 0; k < nullkeys.length; k++) {
|
||||
system.newConstraint(F, nullkeys[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write `length' in argument objects
|
||||
if (av != -1) {
|
||||
int svn = targetST.getConstant( argCount );
|
||||
int lnv = targetST.getConstant("length");
|
||||
newFieldWrite(target, av, lnv, svn);
|
||||
}
|
||||
|
||||
// return values
|
||||
if (instruction.getDef(0) != -1) {
|
||||
PointerKey RF = getPointerKeyForReturnValue( target );
|
||||
PointerKey RA = getPointerKeyForLocal(caller, instruction.getDef(0));
|
||||
system.newConstraint(RA, assignOperator, RF);
|
||||
}
|
||||
|
||||
PointerKey EF = getPointerKeyForExceptionalReturnValue( target );
|
||||
if (SHORT_CIRCUIT_SINGLE_USES && uniqueCatchKey != null) {
|
||||
// e has exactly one use. so, represent e implicitly
|
||||
system.newConstraint(uniqueCatchKey, assignOperator, EF);
|
||||
} else {
|
||||
PointerKey EA = getPointerKeyForLocal(caller, instruction.getDef(1));
|
||||
system.newConstraint(EA, assignOperator, EF);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// string manipulation handling for binary operators
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void handleBinaryOp(final SSABinaryOpInstruction instruction,
|
||||
final CGNode node,
|
||||
final SymbolTable symbolTable,
|
||||
final DefUse du)
|
||||
{
|
||||
int lval = instruction.getDef(0);
|
||||
PointerKey lk = getPointerKeyForLocal(node, lval);
|
||||
final PointsToSetVariable lv = system.findOrCreatePointsToSet(lk);
|
||||
|
||||
final int arg1 = instruction.getUse(0);
|
||||
final int arg2 = instruction.getUse(1);
|
||||
|
||||
class BinaryOperator extends AbstractOperator {
|
||||
|
||||
private CGNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
private SSABinaryOpInstruction getInstruction() {
|
||||
return instruction;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "BinOp: " + getInstruction();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 17 * getInstruction().getUse(0) * getInstruction().getUse(1);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof BinaryOperator) {
|
||||
BinaryOperator op = (BinaryOperator)o;
|
||||
return
|
||||
op.getNode().equals( getNode() ) &&
|
||||
op.getInstruction().getUse(0) == getInstruction().getUse(0) &&
|
||||
op.getInstruction().getUse(1) == getInstruction().getUse(1) &&
|
||||
op.getInstruction().getDef(0) == getInstruction().getDef(0);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private InstanceKey[] getInstancesArray(int vn) {
|
||||
if (contentsAreInvariant(symbolTable, du, vn)) {
|
||||
return getInvariantContents(symbolTable, du, node, vn, JSSSAPropagationCallGraphBuilder.this);
|
||||
} else {
|
||||
PointsToSetVariable v =
|
||||
system.findOrCreatePointsToSet(getPointerKeyForLocal(node,vn));
|
||||
if (v.getValue() == null || v.size() == 0) {
|
||||
return new InstanceKey[0];
|
||||
} else {
|
||||
final Set temp = new HashSet();
|
||||
v.getValue().foreach(new IntSetAction() {
|
||||
public void act(int keyIndex) {
|
||||
temp.add( system.getInstanceKey(keyIndex) );
|
||||
}
|
||||
});
|
||||
|
||||
return (InstanceKey[])temp.toArray(new InstanceKey[temp.size()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isStringConstant(InstanceKey k) {
|
||||
return
|
||||
(k instanceof ConstantKey)
|
||||
&&
|
||||
k.getConcreteType().getReference().equals(JavaScriptTypes.String);
|
||||
}
|
||||
|
||||
private boolean addKey(InstanceKey k) {
|
||||
int n = system.findOrCreateIndexForInstanceKey( k );
|
||||
if (! lv.contains(n)) {
|
||||
lv.add( n );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public byte evaluate(IVariable lhs, final IVariable[] rhs) {
|
||||
boolean doDefault = false;
|
||||
byte changed = NOT_CHANGED;
|
||||
|
||||
InstanceKey[] iks1 = getInstancesArray( arg1 );
|
||||
InstanceKey[] iks2 = getInstancesArray( arg2 );
|
||||
|
||||
if ( (instruction.getOperator() == BinaryOpInstruction.Operator.ADD)
|
||||
&&
|
||||
( getOptions().getTraceStringConstants() ) )
|
||||
{
|
||||
for(int i = 0 ; i < iks1.length; i++) {
|
||||
if (isStringConstant(iks1[i])) {
|
||||
for(int j = 0 ; j < iks2.length; j++) {
|
||||
if (isStringConstant(iks2[j])) {
|
||||
String v1 = (String)((ConstantKey)iks1[i]).getValue();
|
||||
String v2 = (String)((ConstantKey)iks2[j]).getValue();
|
||||
if (v1.indexOf(v2) == -1 && v2.indexOf(v1) == -1) {
|
||||
InstanceKey lvalKey = getInstanceKeyForConstant(v1+v2);
|
||||
if (addKey( lvalKey )) {
|
||||
changed = CHANGED;
|
||||
}
|
||||
} else {
|
||||
doDefault = true;
|
||||
}
|
||||
} else {
|
||||
doDefault = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doDefault = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doDefault = true;
|
||||
}
|
||||
|
||||
if (doDefault) {
|
||||
for(int i = 0; i < iks1.length; i++) {
|
||||
if (addKey(new ConcreteTypeKey(iks1[i].getConcreteType()))) {
|
||||
changed = CHANGED;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < iks2.length; i++) {
|
||||
if (addKey(new ConcreteTypeKey(iks2[i].getConcreteType()))) {
|
||||
changed = CHANGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
BinaryOperator B = new BinaryOperator();
|
||||
if (contentsAreInvariant(symbolTable, du, arg1)) {
|
||||
if (contentsAreInvariant(symbolTable, du, arg2)) {
|
||||
B.evaluate(null, null);
|
||||
} else {
|
||||
system.newConstraint(lk, B, getPointerKeyForLocal(node, arg2));
|
||||
}
|
||||
} else {
|
||||
PointerKey k1 = getPointerKeyForLocal(node, arg1);
|
||||
if (contentsAreInvariant(symbolTable, du, arg2)) {
|
||||
system.newConstraint(lk, B, k1);
|
||||
} else {
|
||||
system.newConstraint(lk, B, k1, getPointerKeyForLocal(node, arg2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IR visitor specialization for JavaScript
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class JSConstraintVisitor extends AstConstraintVisitor implements InstructionVisitor {
|
||||
|
||||
public JSConstraintVisitor(ExplicitCallGraph.ExplicitNode node, IR ir, ExplicitCallGraph callGraph, DefUse du) {
|
||||
super(node, ir, callGraph, du);
|
||||
}
|
||||
|
||||
public void visitEachElementHasNext(EachElementHasNextInstruction inst) {
|
||||
int lval = inst.getDef(0);
|
||||
PointerKey lk = getPointerKeyForLocal(node, lval);
|
||||
|
||||
IClass bool = cha.lookupClass(JavaScriptTypes.Boolean);
|
||||
InstanceKey key = new ConcreteTypeKey( bool );
|
||||
|
||||
system.newConstraint(lk, key);
|
||||
}
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction instruction) {
|
||||
int lval = instruction.getDef(0);
|
||||
PointerKey lk = getPointerKeyForLocal(node, lval);
|
||||
|
||||
IClass string = cha.lookupClass(JavaScriptTypes.String);
|
||||
InstanceKey key = new ConcreteTypeKey( string );
|
||||
|
||||
system.newConstraint(lk, key);
|
||||
}
|
||||
|
||||
public void visitBinaryOp(final SSABinaryOpInstruction instruction) {
|
||||
handleBinaryOp( instruction, node, symbolTable, du );
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
|
||||
newFieldRead(node,
|
||||
instruction.getUse(0),
|
||||
instruction.getUse(1),
|
||||
instruction.getDef(0));
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
|
||||
newFieldWrite(node,
|
||||
instruction.getUse(0),
|
||||
instruction.getUse(1),
|
||||
instruction.getUse(2));
|
||||
}
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
|
||||
PointerKey F = getPointerKeyForLocal(node, instruction.getFunction());
|
||||
|
||||
InstanceKey[][] consts = computeInvariantParameters(instruction);
|
||||
|
||||
PointerKey uniqueCatch = null;
|
||||
if (hasUniqueCatchBlock(instruction, ir)) {
|
||||
uniqueCatch = getUniqueCatchKey(instruction, ir, node);
|
||||
}
|
||||
|
||||
if (contentsAreInvariant(symbolTable, du, instruction.getFunction())) {
|
||||
system.recordImplicitPointsToSet(F);
|
||||
InstanceKey[] ik = getInvariantContents(symbolTable, du, node, instruction.getFunction(), JSSSAPropagationCallGraphBuilder.this);
|
||||
for (int i = 0; i < ik.length; i++) {
|
||||
system.findOrCreateIndexForInstanceKey(ik[i]);
|
||||
CGNode n = getTargetForCall(node, instruction.getCallSite(), ik[i]);
|
||||
if (n != null) {
|
||||
processJSCall(node, instruction, n, ik[i], consts, uniqueCatch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
system.newSideEffect(
|
||||
new JSDispatchOperator(instruction, node, consts, uniqueCatch),
|
||||
F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ConstraintVisitor makeVisitor(ExplicitCallGraph.ExplicitNode node,
|
||||
IR ir,
|
||||
DefUse du,
|
||||
ExplicitCallGraph callGraph)
|
||||
{
|
||||
return new JSConstraintVisitor(node, ir, callGraph, du);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.NodeKey;
|
||||
|
||||
public class JSSyntheticParameterKey extends NodeKey {
|
||||
public static int lengthOffset = -1;
|
||||
|
||||
private final int param;
|
||||
|
||||
public JSSyntheticParameterKey(CGNode node, int param) {
|
||||
super(node);
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof JSSyntheticParameterKey) &&
|
||||
((JSSyntheticParameterKey)o).param == param &&
|
||||
internalEquals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return param*getNode().hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "p" + param + ":" + getNode().getMethod().getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.impl.*;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.*;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* 0-1-CFA Call graph builder, optimized to not disambiguate instances of
|
||||
* "uninteresting" types
|
||||
*/
|
||||
public class JSZeroXCFABuilder extends JSCFABuilder {
|
||||
|
||||
/**
|
||||
* @param cha
|
||||
* @param warnings
|
||||
* @param entrypoints
|
||||
* @param bypass
|
||||
* @param contextProvider
|
||||
*/
|
||||
public JSZeroXCFABuilder(ClassHierarchy cha,
|
||||
WarningSet warnings,
|
||||
AnalysisOptions options,
|
||||
ContextSelector appContextSelector,
|
||||
SSAContextInterpreter appContextInterpreter,
|
||||
ReflectionSpecification reflect,
|
||||
int instancePolicy) {
|
||||
super(cha, warnings, options);
|
||||
|
||||
SSAContextInterpreter contextInterpreter =
|
||||
makeDefaultContextInterpreters(appContextInterpreter, options, cha, reflect, warnings);
|
||||
setContextInterpreter( contextInterpreter );
|
||||
|
||||
options.setSelector(
|
||||
new JavaScriptConstructTargetSelector(
|
||||
cha,
|
||||
options.getMethodTargetSelector(),
|
||||
contextInterpreter,
|
||||
warnings));
|
||||
|
||||
ContextSelector def = new DefaultContextSelector(cha,options.getMethodTargetSelector());
|
||||
ContextSelector contextSelector =
|
||||
appContextSelector == null?
|
||||
def:
|
||||
new DelegatingContextSelector(appContextSelector, def);
|
||||
|
||||
setContextSelector(contextSelector);
|
||||
|
||||
setInstanceKeys(
|
||||
new JavaScriptScopeMappingInstanceKeys(cha, this,
|
||||
new ZeroXInstanceKeys(options, cha, contextInterpreter, warnings, instancePolicy)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param options
|
||||
* options that govern call graph construction
|
||||
* @param cha
|
||||
* governing class hierarchy
|
||||
* @param cl
|
||||
* classloader that can find DOMO resources
|
||||
* @param scope
|
||||
* representation of the analysis scope
|
||||
* @param xmlFiles
|
||||
* set of Strings that are names of XML files holding bypass logic
|
||||
* specifications.
|
||||
* @param dmd
|
||||
* deployment descriptor abstraction
|
||||
* @return a 0-1-Opt-CFA Call Graph Builder.
|
||||
*/
|
||||
public static JSCFABuilder make(AnalysisOptions options, ClassHierarchy cha, ClassLoader cl, AnalysisScope scope,
|
||||
String[] xmlFiles, WarningSet warnings, byte instancePolicy) {
|
||||
|
||||
com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha, warnings);
|
||||
for (int i = 0; i < xmlFiles.length; i++) {
|
||||
com.ibm.wala.ipa.callgraph.impl.Util.addBypassLogic(options, scope, cl, xmlFiles[i], cha);
|
||||
}
|
||||
|
||||
return new JSZeroXCFABuilder(cha, warnings, options, null, null, options.getReflectionSpec(), instancePolicy);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.domo.ipa.callgraph.propagation.PropagationCallGraphBuilder#getDefaultDispatchBoundHeuristic()
|
||||
*/
|
||||
protected byte getDefaultDispatchBoundHeuristic() {
|
||||
return AnalysisOptions.NO_DISPATCH_BOUND;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,549 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.cast.js.ipa.summaries.*;
|
||||
import com.ibm.wala.cast.js.loader.*;
|
||||
import com.ibm.wala.cast.js.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.summaries.MethodSummary;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final ClassHierarchy cha;
|
||||
private final MethodTargetSelector base;
|
||||
private final SSAContextInterpreter interpreter;
|
||||
private final WarningSet warnings;
|
||||
|
||||
private final Map constructors = new HashMap();
|
||||
|
||||
private class JavaScriptConstructor extends JavaScriptSummarizedFunction {
|
||||
private final String toStringExtra;
|
||||
|
||||
private JavaScriptConstructor(MethodReference ref,
|
||||
MethodSummary summary,
|
||||
IClass declaringClass,
|
||||
String toStringExtra)
|
||||
{
|
||||
super(ref, summary, declaringClass);
|
||||
this.toStringExtra = toStringExtra;
|
||||
}
|
||||
|
||||
private JavaScriptConstructor(MethodReference ref,
|
||||
MethodSummary summary,
|
||||
IClass declaringClass)
|
||||
{
|
||||
this(ref, summary, declaringClass, "");
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "<ctor for " + getReference().getDeclaringClass() + toStringExtra + ">";
|
||||
}
|
||||
}
|
||||
|
||||
public JavaScriptConstructTargetSelector(ClassHierarchy cha,
|
||||
MethodTargetSelector base,
|
||||
SSAContextInterpreter interpreter,
|
||||
WarningSet warnings)
|
||||
{
|
||||
this.cha = cha;
|
||||
this.base = base;
|
||||
this.interpreter = interpreter;
|
||||
this.warnings = warnings;
|
||||
}
|
||||
|
||||
private IMethod record(Object key, IMethod m) {
|
||||
constructors.put(key, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
private IMethod makeNullaryValueConstructor(IClass cls, Object value) {
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( cls.getReference() );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(4, 1, "prototype"));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
5,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Object)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 4));
|
||||
|
||||
S.addConstant(new Integer(8), new ConstantValue(value));
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(5, "$value", 8));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeUnaryValueConstructor(IClass cls) {
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( cls.getReference() );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(5, 1, "prototype"));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
6,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Object)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(6, "prototype", 5));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(6, "$value", 2));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(6, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeValueConstructor(IClass cls, int nargs, Object value) {
|
||||
Assertions._assert(nargs == 0 || nargs == 1);
|
||||
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
else return
|
||||
record(
|
||||
key,
|
||||
(nargs==0)?
|
||||
makeNullaryValueConstructor(cls, value):
|
||||
makeUnaryValueConstructor(cls));
|
||||
}
|
||||
|
||||
private IMethod makeNullaryObjectConstructor(IClass cls) {
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Object );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(4, 1, "prototype"));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
5,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Object)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 4));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeUnaryObjectConstructor(IClass cls) {
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Object );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(2, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeObjectConstructor(IClass cls, int nargs) {
|
||||
Assertions._assert(nargs == 0 || nargs == 1);
|
||||
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
else return
|
||||
record(
|
||||
key,
|
||||
(nargs==0)?
|
||||
makeNullaryObjectConstructor(cls):
|
||||
makeUnaryObjectConstructor(cls));
|
||||
}
|
||||
|
||||
private IMethod makeObjectCall(IClass cls, int nargs) {
|
||||
Assertions._assert(nargs == 0);
|
||||
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
else return
|
||||
record(
|
||||
key,
|
||||
makeNullaryObjectConstructor(cls));
|
||||
}
|
||||
|
||||
private IMethod makeArrayLengthConstructor(IClass cls) {
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Array );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(5, 1, "prototype"));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
6,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Array)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(6, "prototype", 5));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(6, "length", 2));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(6, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeArrayContentsConstructor(IClass cls, int nargs) {
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Array );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, nargs+1);
|
||||
|
||||
S.addConstant(new Integer(nargs+3), new ConstantValue("prototype"));
|
||||
S.addStatement(new JavaScriptPropertyRead(nargs+4, 1, nargs+3));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
nargs+5,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Array)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(nargs+5, "prototype", nargs+4));
|
||||
|
||||
S.addConstant(new Integer(nargs+7), new ConstantValue(nargs));
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(nargs+5, "length", nargs+7));
|
||||
|
||||
int vn = nargs+9;
|
||||
for(int i = 0; i < nargs; i++, vn+=2) {
|
||||
S.addConstant(new Integer(vn), new ConstantValue(i));
|
||||
S.addStatement(new JavaScriptPropertyWrite(nargs+5, vn, i+1));
|
||||
}
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeArrayConstructor(IClass cls, int nargs) {
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
else return
|
||||
record(
|
||||
key,
|
||||
(nargs==1)?
|
||||
makeArrayLengthConstructor(cls):
|
||||
makeArrayContentsConstructor(cls, nargs));
|
||||
}
|
||||
|
||||
private IMethod makeNullaryStringCall(IClass cls) {
|
||||
MethodReference ref =
|
||||
AstMethodReference.fnReference( JavaScriptTypes.String );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
|
||||
|
||||
S.addConstant(new Integer(2), new ConstantValue(""));
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(2, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeUnaryStringCall(IClass cls) {
|
||||
MethodReference ref =
|
||||
AstMethodReference.fnReference( JavaScriptTypes.String );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(4, 2, "toString"));
|
||||
|
||||
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
|
||||
S.addStatement(new JavaScriptInvoke(4, 5, new int[]{2}, 6, cs));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeStringCall(IClass cls, int nargs) {
|
||||
Assertions._assert(nargs == 0 || nargs == 1);
|
||||
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
else return
|
||||
record(
|
||||
key,
|
||||
(nargs==0)?
|
||||
makeNullaryStringCall(cls):
|
||||
makeUnaryStringCall(cls));
|
||||
}
|
||||
|
||||
private IMethod makeNullaryNumberCall(IClass cls) {
|
||||
MethodReference ref =
|
||||
AstMethodReference.fnReference( JavaScriptTypes.Number );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
|
||||
|
||||
S.addConstant(new Integer(2), new ConstantValue(0.0));
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(2, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeUnaryNumberCall(IClass cls) {
|
||||
MethodReference ref =
|
||||
AstMethodReference.fnReference( JavaScriptTypes.Number );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(4, 2, "toNumber"));
|
||||
|
||||
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
|
||||
S.addStatement(new JavaScriptInvoke(4, 5, new int[]{2}, 6, cs));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
|
||||
|
||||
return new JavaScriptConstructor(ref, S, cls);
|
||||
}
|
||||
|
||||
private IMethod makeNumberCall(IClass cls, int nargs) {
|
||||
Assertions._assert(nargs == 0 || nargs == 1);
|
||||
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
else return
|
||||
record(
|
||||
key,
|
||||
(nargs==0)?
|
||||
makeNullaryNumberCall(cls):
|
||||
makeUnaryNumberCall(cls));
|
||||
}
|
||||
|
||||
private IMethod makeFunctionConstructor(IClass receiver, IClass cls) {
|
||||
if (constructors.containsKey(cls)) return (IMethod)constructors.get(cls);
|
||||
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( receiver.getReference() );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(4, 1, "prototype"));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
5,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
cls.getReference())));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 4));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
7,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Object)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 7));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(7, "constructor", 5));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
|
||||
|
||||
if (receiver != cls)
|
||||
return record(receiver, new JavaScriptConstructor(ref, S, receiver, "("+cls.getReference().getName()+")"));
|
||||
else
|
||||
return record(receiver, new JavaScriptConstructor(ref, S, receiver));
|
||||
}
|
||||
|
||||
private int ctorCount = 0;
|
||||
|
||||
private IMethod makeFunctionConstructor(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass cls, int nargs) {
|
||||
SymbolTable ST = callerIR.getSymbolTable();
|
||||
|
||||
if (nargs == 0) {
|
||||
return makeFunctionConstructor(cls, cls);
|
||||
} else if (nargs==1) {
|
||||
if (ST.isStringConstant(callStmt.getUse(1))) {
|
||||
TypeReference ref =
|
||||
TypeReference.findOrCreate(
|
||||
JavaScriptTypes.jsLoader,
|
||||
TypeName.string2TypeName(
|
||||
(String)ST.getStringValue(callStmt.getUse(1)) ));
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println("ctor type name is " + (String)ST.getStringValue(callStmt.getUse(1)));
|
||||
}
|
||||
|
||||
IClass cls2 = cha.lookupClass( ref );
|
||||
if (cls2 != null) {
|
||||
return makeFunctionConstructor(cls, cls2);
|
||||
}
|
||||
}
|
||||
|
||||
return makeFunctionConstructor(cls, cls);
|
||||
} else {
|
||||
Assertions._assert(nargs > 1);
|
||||
JavaScriptLoader cl = (JavaScriptLoader)
|
||||
cha.getLoader(JavaScriptTypes.jsLoader);
|
||||
|
||||
for(int i = 1; i < callStmt.getNumberOfUses(); i++)
|
||||
if (! ST.isStringConstant(callStmt.getUse(i)))
|
||||
return makeFunctionConstructor(cls, cls);
|
||||
|
||||
StringBuffer fun = new StringBuffer("function _fromctor (");
|
||||
for(int j = 1; j < callStmt.getNumberOfUses()-1; j++) {
|
||||
if (j != 1) fun.append(",");
|
||||
fun.append( ST.getStringValue(callStmt.getUse(j)) );
|
||||
}
|
||||
|
||||
fun.append(") {");
|
||||
fun.append(ST.getStringValue(callStmt.getUse(callStmt.getNumberOfUses()-1)));
|
||||
fun.append("}");
|
||||
|
||||
try {
|
||||
String fileName = "ctor " + ++ctorCount;
|
||||
File f = new File(System.getProperty("java.io.tmpdir")+File.separator+fileName);
|
||||
FileWriter FO = new FileWriter(f);
|
||||
FO.write( fun.toString() );
|
||||
FO.close();
|
||||
(Util.getTranslatorFactory().make(cl)).translate(new SourceFileModule(f, System.getProperty("java.io.tmpdir")), fileName);
|
||||
f.delete();
|
||||
IClass fcls = cl.lookupClass("Lctor " + ctorCount + "/_fromctor", cha);
|
||||
cha.addClass( fcls );
|
||||
|
||||
if (DEBUG)
|
||||
Trace.println("looking for ctor " + ctorCount + " and got " + fcls);
|
||||
|
||||
if (fcls != null)
|
||||
return makeFunctionConstructor(cls, fcls);
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
|
||||
return makeFunctionConstructor(cls, cls);
|
||||
}
|
||||
}
|
||||
|
||||
private IMethod makeFunctionObjectConstructor(IClass cls, int nargs) {
|
||||
Object key = new Pair(cls, new Integer(nargs));
|
||||
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
|
||||
|
||||
MethodReference ref =
|
||||
JavaScriptMethods.makeCtorReference( cls.getReference() );
|
||||
JavaScriptSummary S = new JavaScriptSummary(ref, nargs+1);
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyRead(nargs+4, 1, "prototype"));
|
||||
|
||||
S.addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
nargs+5,
|
||||
NewSiteReference.make(
|
||||
S.getNextProgramCounter(),
|
||||
JavaScriptTypes.Object)));
|
||||
|
||||
S.addStatement(new JavaScriptStaticPropertyWrite(nargs+5, "prototype", nargs+4));
|
||||
|
||||
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
|
||||
int[] args = new int[ nargs+1 ];
|
||||
args[0] = nargs+5;
|
||||
for(int i = 0; i < nargs; i++) args[i+1] = i+2;
|
||||
S.addStatement(new JavaScriptInvoke(1, nargs+7, args, nargs+8, cs));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(nargs+7, false));
|
||||
|
||||
S.addStatement(SSAInstructionFactory.ReturnInstruction(nargs+5, false));
|
||||
|
||||
return record(key, new JavaScriptConstructor(ref, S, cls));
|
||||
}
|
||||
|
||||
private IMethod findOrCreateConstructorMethod(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass receiver, int nargs) {
|
||||
if (receiver.getReference().equals(JavaScriptTypes.Object))
|
||||
return makeObjectConstructor(receiver, nargs);
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.Array))
|
||||
return makeArrayConstructor(receiver, nargs);
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.String))
|
||||
return makeValueConstructor(receiver, nargs, "");
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.Boolean)) {
|
||||
Assertions._assert(nargs == 1);
|
||||
return makeValueConstructor(receiver, nargs, null);
|
||||
} else if (receiver.getReference().equals(JavaScriptTypes.Number))
|
||||
return makeValueConstructor(receiver, nargs, new Integer(0));
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.Function))
|
||||
return makeFunctionConstructor(callerIR, callStmt, receiver, nargs);
|
||||
else if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody)))
|
||||
return makeFunctionObjectConstructor(receiver, nargs);
|
||||
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private IMethod findOrCreateCallMethod(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass receiver, int nargs) {
|
||||
if (receiver.getReference().equals(JavaScriptTypes.Object))
|
||||
return makeObjectCall(receiver, nargs);
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.Array))
|
||||
return makeArrayConstructor(receiver, nargs);
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.String))
|
||||
return makeStringCall(receiver, nargs);
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.Number))
|
||||
return makeNumberCall(receiver, nargs);
|
||||
else if (receiver.getReference().equals(JavaScriptTypes.Function))
|
||||
return makeFunctionConstructor(callerIR, callStmt, receiver, nargs);
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IMethod getCalleeTarget(CGNode caller,
|
||||
CallSiteReference site,
|
||||
IClass receiver)
|
||||
{
|
||||
if (site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference)) {
|
||||
Assertions._assert(cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.Root)));
|
||||
IR callerIR = interpreter.getIR(caller, warnings);
|
||||
SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls( site );
|
||||
Assertions._assert( callStmts.length == 1 );
|
||||
int nargs = callStmts[0].getNumberOfUses();
|
||||
return findOrCreateConstructorMethod(callerIR, callStmts[0], receiver, nargs-1);
|
||||
} else {
|
||||
return base.getCalleeTarget(caller, site, receiver);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mightReturnSyntheticMethod(CGNode caller,
|
||||
CallSiteReference site)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean mightReturnSyntheticMethod(MethodReference declaredTarget) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
|
||||
public class JavaScriptEntryPoints extends ScriptEntryPoints {
|
||||
|
||||
public JavaScriptEntryPoints(ClassHierarchy cha, IClassLoader loader) {
|
||||
super(cha, loader.lookupClass(JavaScriptTypes.Script.getName(), cha));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys;
|
||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader.JavaScriptMethodObject;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.loader.AstMethod.LexicalParent;
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.*;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.Selector;
|
||||
|
||||
public class JavaScriptScopeMappingInstanceKeys extends ScopeMappingInstanceKeys {
|
||||
|
||||
private final ClassHierarchy cha;
|
||||
private final IClass codeBody;
|
||||
|
||||
public JavaScriptScopeMappingInstanceKeys(ClassHierarchy cha,
|
||||
PropagationCallGraphBuilder builder,
|
||||
InstanceKeyFactory basic)
|
||||
{
|
||||
super(builder, basic);
|
||||
this.cha = cha;
|
||||
|
||||
this.codeBody = cha.lookupClass(JavaScriptTypes.CodeBody);
|
||||
}
|
||||
|
||||
protected LexicalParent[] getParents(InstanceKey base) {
|
||||
JavaScriptMethodObject function = (JavaScriptMethodObject)
|
||||
base.getConcreteType().getMethod(AstMethodReference.fnSelector);
|
||||
|
||||
return function==null? new LexicalParent[0]: function.getParents();
|
||||
}
|
||||
|
||||
protected boolean needsScopeMappingKey(InstanceKey base) {
|
||||
return
|
||||
cha.isSubclassOf(base.getConcreteType(), codeBody)
|
||||
&&
|
||||
getParents(base).length > 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.ibm.wala.cast.ipa.callgraph.*;
|
||||
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
|
||||
import com.ibm.wala.cast.js.loader.*;
|
||||
import com.ibm.wala.cast.js.translator.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
public class Util extends com.ibm.wala.cast.ipa.callgraph.Util {
|
||||
|
||||
private static JavaScriptTranslatorFactory translatorFactory =
|
||||
new JavaScriptTranslatorFactory.CAstRhinoFactory();
|
||||
|
||||
public static void setTranslatorFactory(JavaScriptTranslatorFactory translatorFactory) {
|
||||
Util.translatorFactory = translatorFactory;
|
||||
}
|
||||
|
||||
public static JavaScriptTranslatorFactory getTranslatorFactory() {
|
||||
return translatorFactory;
|
||||
}
|
||||
|
||||
public static AnalysisOptions
|
||||
makeOptions(AnalysisScope scope,
|
||||
boolean keepIRs,
|
||||
ClassHierarchy cha,
|
||||
Entrypoints roots,
|
||||
final WarningSet warnings)
|
||||
{
|
||||
final AnalysisOptions options =
|
||||
new AnalysisOptions(scope, AstIRFactory.makeDefaultFactory(keepIRs), roots);
|
||||
|
||||
com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha, warnings);
|
||||
options.setSelector(new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector()));
|
||||
|
||||
options.setConstantType(String.class, JavaScriptTypes.String);
|
||||
options.setConstantType(Integer.class, JavaScriptTypes.Number);
|
||||
options.setConstantType(Float.class, JavaScriptTypes.Number);
|
||||
options.setConstantType(Double.class, JavaScriptTypes.Number);
|
||||
options.setConstantType(null, JavaScriptTypes.Null);
|
||||
|
||||
options.setUseConstantSpecificKeys( true );
|
||||
|
||||
options.setUseStacksForLexicalScoping( true );
|
||||
|
||||
options.getSSAOptions().setPreserveNames( true );
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static JavaScriptLoaderFactory makeLoaders() {
|
||||
return new JavaScriptLoaderFactory(translatorFactory);
|
||||
}
|
||||
|
||||
public static AnalysisScope
|
||||
makeScope(String[] files, JavaScriptLoaderFactory loaders)
|
||||
throws IOException
|
||||
{
|
||||
return new CAstAnalysisScope( files, loaders );
|
||||
}
|
||||
|
||||
public static AnalysisScope
|
||||
makeScope(SourceFileModule[] files, JavaScriptLoaderFactory loaders)
|
||||
throws IOException
|
||||
{
|
||||
return new CAstAnalysisScope( files, loaders );
|
||||
}
|
||||
|
||||
public static AnalysisScope
|
||||
makeScope(URL[] files, JavaScriptLoaderFactory loaders)
|
||||
throws IOException
|
||||
{
|
||||
return new CAstAnalysisScope( files, loaders );
|
||||
}
|
||||
|
||||
public static ClassHierarchy
|
||||
makeHierarchy(AnalysisScope scope,
|
||||
ClassLoaderFactory loaders,
|
||||
WarningSet warnings)
|
||||
throws ClassHierarchyException
|
||||
{
|
||||
return ClassHierarchy.make(
|
||||
scope,
|
||||
loaders,
|
||||
warnings,
|
||||
JavaScriptTypes.Root);
|
||||
}
|
||||
|
||||
public static Entrypoints makeScriptRoots(ClassHierarchy cha) {
|
||||
return new JavaScriptEntryPoints(
|
||||
cha,
|
||||
cha.getLoader( JavaScriptTypes.jsLoader ));
|
||||
}
|
||||
|
||||
public static Collection getNodes(CallGraph CG, String funName) {
|
||||
boolean ctor = funName.startsWith("ctor:");
|
||||
TypeReference TR = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName( "L"+(ctor?funName.substring(5):funName) ));
|
||||
MethodReference MR = ctor? JavaScriptMethods.makeCtorReference(TR): AstMethodReference.fnReference(TR);
|
||||
return CG.getNodes(MR);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.summaries;
|
||||
|
||||
import com.ibm.wala.cast.js.cfg.JSInducedCFG;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||
import com.ibm.wala.ipa.summaries.MethodSummary;
|
||||
import com.ibm.wala.ipa.summaries.SummarizedMethod;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
public class JavaScriptSummarizedFunction extends SummarizedMethod {
|
||||
|
||||
public JavaScriptSummarizedFunction(MethodReference ref,
|
||||
MethodSummary summary,
|
||||
IClass declaringClass)
|
||||
{
|
||||
super(ref, summary, declaringClass);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return this==o;
|
||||
}
|
||||
|
||||
public InducedCFG makeControlFlowGraph() {
|
||||
return new JSInducedCFG(getStatements(new WarningSet()), this, Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ipa.summaries;
|
||||
|
||||
import com.ibm.wala.cast.js.ssa.JavaScriptNewInstruction;
|
||||
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.ipa.summaries.MethodSummary;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class JavaScriptSummary extends MethodSummary {
|
||||
|
||||
private final int declaredParameters;
|
||||
|
||||
public JavaScriptSummary(MethodReference ref, int declaredParameters) {
|
||||
super(ref);
|
||||
this.declaredParameters = declaredParameters;
|
||||
addStatement(
|
||||
new JavaScriptNewInstruction(
|
||||
declaredParameters+1,
|
||||
NewSiteReference.make(
|
||||
getNextProgramCounter(),
|
||||
JavaScriptTypes.Array)));
|
||||
|
||||
}
|
||||
|
||||
public int getNumberOfParameters() {
|
||||
return declaredParameters;
|
||||
}
|
||||
|
||||
public TypeReference getParameterType(int i) {
|
||||
return JavaScriptTypes.Root;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.loader;
|
||||
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
|
||||
public class JSCallSiteReference extends CallSiteReference {
|
||||
|
||||
// this must be distinct from java invoke codes.
|
||||
// see com.ibm.shrikeBT.BytecodeConstants
|
||||
public static enum Dispatch implements IInvokeInstruction.IDispatch {
|
||||
JS_CALL;
|
||||
}
|
||||
|
||||
public JSCallSiteReference(MethodReference ref, int pc) {
|
||||
super(pc, ref);
|
||||
}
|
||||
|
||||
public JSCallSiteReference(int pc) {
|
||||
this(AstMethodReference.fnReference(JavaScriptTypes.CodeBody), pc);
|
||||
}
|
||||
|
||||
public IInvokeInstruction.IDispatch getInvocationCode() {
|
||||
return Dispatch.JS_CALL;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "JSCall@" + getProgramCounter();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.loader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.cast.js.translator.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.loader.*;
|
||||
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
|
||||
import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
|
||||
import com.ibm.wala.cast.tree.*;
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.cfg.AbstractCFG;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
||||
public class JavaScriptLoader implements IClassLoader {
|
||||
private final Map types = new HashMap();
|
||||
private final JavaScriptTranslatorFactory translatorFactory;
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
JavaScriptLoader(ClassHierarchy cha,
|
||||
JavaScriptTranslatorFactory translatorFactory)
|
||||
{
|
||||
this.cha = cha;
|
||||
this.translatorFactory = translatorFactory;
|
||||
}
|
||||
|
||||
class JavaScriptClass extends AstClass {
|
||||
private IClass superClass;
|
||||
|
||||
private JavaScriptClass(IClassLoader loader,
|
||||
TypeReference classRef,
|
||||
TypeReference superRef,
|
||||
CAstSourcePositionMap.Position sourcePosition) {
|
||||
super(sourcePosition,
|
||||
classRef.getName(),
|
||||
loader,
|
||||
(short)0,
|
||||
Collections.EMPTY_MAP,
|
||||
Collections.EMPTY_MAP);
|
||||
types.put(classRef.getName(), this);
|
||||
superClass = superRef==null? null: loader.lookupClass(superRef.getName(), cha);
|
||||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "JS:" + getReference().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getDirectInterfaces() throws ClassHierarchyException {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClass getSuperclass() throws ClassHierarchyException {
|
||||
return superClass;
|
||||
}
|
||||
}
|
||||
|
||||
class JavaScriptRootClass extends AstDynamicPropertyClass {
|
||||
|
||||
private JavaScriptRootClass(IClassLoader loader,
|
||||
CAstSourcePositionMap.Position sourcePosition)
|
||||
{
|
||||
super(sourcePosition,
|
||||
JavaScriptTypes.Root.getName(),
|
||||
loader,
|
||||
(short)0,
|
||||
Collections.EMPTY_MAP,
|
||||
JavaScriptTypes.Root);
|
||||
|
||||
types.put(JavaScriptTypes.Root.getName(), this);
|
||||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "JS Root:" + getReference().toString();
|
||||
}
|
||||
|
||||
public Collection getDirectInterfaces() throws ClassHierarchyException {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public IClass getSuperclass() throws ClassHierarchyException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class JavaScriptCodeBody extends AstFunctionClass {
|
||||
|
||||
public JavaScriptCodeBody(TypeReference codeName,
|
||||
TypeReference parent,
|
||||
IClassLoader loader,
|
||||
CAstSourcePositionMap.Position sourcePosition)
|
||||
{
|
||||
super(codeName, parent, loader, sourcePosition);
|
||||
types.put(codeName.getName(), this);
|
||||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
private IMethod setCodeBody(IMethod codeBody) {
|
||||
this.functionBody = codeBody;
|
||||
return codeBody;
|
||||
}
|
||||
}
|
||||
|
||||
private final Set functionQualifiers;
|
||||
|
||||
{
|
||||
functionQualifiers = new HashSet();
|
||||
functionQualifiers.add(CAstQualifier.PUBLIC);
|
||||
functionQualifiers.add(CAstQualifier.FINAL);
|
||||
}
|
||||
|
||||
public class JavaScriptMethodObject extends AstMethod {
|
||||
|
||||
JavaScriptMethodObject(JavaScriptCodeBody cls,
|
||||
AbstractCFG cfg,
|
||||
SymbolTable symtab,
|
||||
boolean hasCatchBlock,
|
||||
TypeReference[][] caughtTypes,
|
||||
LexicalInformation lexicalInfo,
|
||||
DebuggingInformation debugInfo)
|
||||
{
|
||||
super(cls,
|
||||
functionQualifiers,
|
||||
cfg,
|
||||
symtab,
|
||||
AstMethodReference.fnReference(cls.getReference()),
|
||||
hasCatchBlock,
|
||||
caughtTypes,
|
||||
lexicalInfo,
|
||||
debugInfo);
|
||||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "<Code body of " + cls + ">";
|
||||
}
|
||||
|
||||
public TypeReference[] getDeclaredExceptions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public LexicalParent[] getParents() {
|
||||
if (lexicalInfo == null) return new LexicalParent[ 0 ];
|
||||
|
||||
final String[] parents = lexicalInfo.getScopingParents();
|
||||
|
||||
if (parents == null) return new LexicalParent[ 0 ];
|
||||
|
||||
LexicalParent result[] =
|
||||
new LexicalParent[ parents.length ];
|
||||
|
||||
for(int i = 0; i < parents.length; i++) {
|
||||
final int hack = i;
|
||||
final AstMethod method = (AstMethod) lookupClass(parents[i], cha).getMethod(AstMethodReference.fnSelector);
|
||||
result[i] = new LexicalParent() {
|
||||
public String getName() { return parents[hack]; }
|
||||
public AstMethod getMethod() { return method; }
|
||||
};
|
||||
|
||||
Trace.println("parent " + result[i].getName() + " is " + result[i].getMethod());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getLocalVariableName(int bcIndex, int localNumber) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasLocalVariableTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getMaxLocals() {
|
||||
Assertions.UNREACHABLE();
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getMaxStackHeight() {
|
||||
Assertions.UNREACHABLE();
|
||||
return -1;
|
||||
}
|
||||
|
||||
public TypeReference getParameterType(int i) {
|
||||
return JavaScriptTypes.Root;
|
||||
}
|
||||
}
|
||||
|
||||
public IClass
|
||||
defineCodeBodyType(String name,
|
||||
TypeReference P,
|
||||
CAstSourcePositionMap.Position sourcePosition)
|
||||
{
|
||||
return
|
||||
new JavaScriptCodeBody(
|
||||
TypeReference.findOrCreate(
|
||||
JavaScriptTypes.jsLoader,
|
||||
TypeName.string2TypeName( name )),
|
||||
P,
|
||||
this,
|
||||
sourcePosition);
|
||||
}
|
||||
|
||||
public IClass
|
||||
defineFunctionType(String name, CAstSourcePositionMap.Position pos)
|
||||
{
|
||||
return defineCodeBodyType(name, JavaScriptTypes.Function, pos);
|
||||
}
|
||||
|
||||
public IClass
|
||||
defineScriptType(String name, CAstSourcePositionMap.Position pos)
|
||||
{
|
||||
return defineCodeBodyType(name, JavaScriptTypes.Script, pos);
|
||||
}
|
||||
|
||||
public IMethod defineCodeBodyCode(String clsName,
|
||||
AbstractCFG cfg,
|
||||
SymbolTable symtab,
|
||||
boolean hasCatchBlock,
|
||||
TypeReference[][] caughtTypes,
|
||||
LexicalInformation lexicalInfo,
|
||||
DebuggingInformation debugInfo)
|
||||
{
|
||||
JavaScriptCodeBody C = (JavaScriptCodeBody) lookupClass(clsName, cha);
|
||||
Assertions._assert(C != null, clsName);
|
||||
return C.setCodeBody(new JavaScriptMethodObject(C, cfg, symtab, hasCatchBlock, caughtTypes, lexicalInfo, debugInfo));
|
||||
}
|
||||
|
||||
final JavaScriptRootClass ROOT =
|
||||
new JavaScriptRootClass(this, null);
|
||||
final JavaScriptClass UNDEFINED =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Undefined, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass PRIMITIVES =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Primitives, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass STRING =
|
||||
new JavaScriptClass(this, JavaScriptTypes.String, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass NULL =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Null, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass BOOLEAN =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Boolean, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass NUMBER =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Number, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass DATE =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Date, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass REGEXP =
|
||||
new JavaScriptClass(this, JavaScriptTypes.RegExp, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass ARRAY =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Array, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass OBJECT =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Object, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass TYPE_ERROR =
|
||||
new JavaScriptClass(this, JavaScriptTypes.TypeError, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass CODE_BODY =
|
||||
new JavaScriptClass(this, JavaScriptTypes.CodeBody, JavaScriptTypes.Root, null);
|
||||
final JavaScriptClass FUNCTION =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Function, JavaScriptTypes.CodeBody, null);
|
||||
final JavaScriptClass SCRIPT =
|
||||
new JavaScriptClass(this, JavaScriptTypes.Script, JavaScriptTypes.CodeBody, null);
|
||||
|
||||
public IClass lookupClass(String className, ClassHierarchy cha) {
|
||||
Assertions._assert(this.cha == cha);
|
||||
return (IClass) types.get( TypeName.string2TypeName(className) );
|
||||
}
|
||||
|
||||
public IClass lookupClass(TypeName className, ClassHierarchy cha) {
|
||||
Assertions._assert(this.cha == cha);
|
||||
return (IClass) types.get( className );
|
||||
}
|
||||
|
||||
public ClassLoaderReference getReference() {
|
||||
return JavaScriptTypes.jsLoader;
|
||||
}
|
||||
|
||||
public Iterator iterateAllClasses() {
|
||||
return types.values().iterator();
|
||||
}
|
||||
|
||||
public int getNumberOfClasses() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Atom getName() {
|
||||
return getReference().getName();
|
||||
}
|
||||
|
||||
public int getNumberOfMethods() {
|
||||
return types.size();
|
||||
}
|
||||
|
||||
public String getSourceFileName(IClass klass) {
|
||||
return klass.getSourceFileName();
|
||||
}
|
||||
|
||||
public IClassLoader getParent() {
|
||||
// currently, JavaScript land does not interact with any other loaders
|
||||
Assertions.UNREACHABLE("JavaScriptLoader.getParent() called?!?");
|
||||
return null;
|
||||
}
|
||||
|
||||
public void init(Set modules) throws IOException {
|
||||
translatorFactory.make(this).translate(modules);
|
||||
}
|
||||
|
||||
public void removeAll(Collection toRemove) {
|
||||
Set keys = new HashSet();
|
||||
|
||||
for(Iterator EE = types.entrySet().iterator(); EE.hasNext(); ) {
|
||||
Map.Entry E = (Map.Entry)EE.next();
|
||||
if (toRemove.contains( E.getValue() )) {
|
||||
keys.add( E.getKey() );
|
||||
}
|
||||
}
|
||||
|
||||
for(Iterator KK = keys.iterator(); KK.hasNext(); ) {
|
||||
types.remove( KK.next() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.loader;
|
||||
|
||||
import com.ibm.wala.cast.js.translator.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.loader.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
import com.ibm.wala.types.*;
|
||||
|
||||
public class JavaScriptLoaderFactory extends SingleClassLoaderFactory {
|
||||
private final JavaScriptTranslatorFactory translatorFactory;
|
||||
|
||||
public JavaScriptLoaderFactory(JavaScriptTranslatorFactory factory) {
|
||||
this.translatorFactory = factory;
|
||||
}
|
||||
|
||||
protected IClassLoader makeTheLoader(ClassHierarchy cha) {
|
||||
return new JavaScriptLoader( cha, translatorFactory );
|
||||
}
|
||||
|
||||
public ClassLoaderReference getTheReference() {
|
||||
return JavaScriptTypes.jsLoader;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstAbstractInstructionVisitor;
|
||||
|
||||
public class AbstractInstructionVisitor
|
||||
extends AstAbstractInstructionVisitor
|
||||
implements InstructionVisitor
|
||||
{
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
|
||||
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
|
||||
|
||||
}
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
|
||||
|
||||
}
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction instruction) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstInstructionVisitor;
|
||||
|
||||
public interface InstructionVisitor extends AstInstructionVisitor {
|
||||
|
||||
public void visitJavaScriptInvoke(JavaScriptInvoke instruction);
|
||||
|
||||
public void visitTypeOf(JavaScriptTypeOfInstruction instruction);
|
||||
|
||||
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction);
|
||||
|
||||
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction);
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaScriptInvoke extends AbstractLexicalInvoke {
|
||||
/**
|
||||
* The value numbers of the arguments passed to the call.
|
||||
*/
|
||||
private final int[] params;
|
||||
|
||||
private int function;
|
||||
|
||||
public JavaScriptInvoke(int function, int result, int[] params, int exception, CallSiteReference site) {
|
||||
super(result, exception, site);
|
||||
this.function = function;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
private JavaScriptInvoke(int function, int result, int[] params, int exception, CallSiteReference site, Access[] lexicalReads, Access[] lexicalWrites) {
|
||||
super(result, exception, site, lexicalReads, lexicalWrites);
|
||||
this.function = function;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor InvokeInstruction. This case for void return values
|
||||
* @param i
|
||||
* @param params
|
||||
*/
|
||||
public JavaScriptInvoke(int function, int[] params, int exception, CallSiteReference site) {
|
||||
this(function, -1, params, exception, site);
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
int fn = function;
|
||||
int newParams[] = params;
|
||||
Access[] reads = lexicalReads;
|
||||
|
||||
if (uses != null) {
|
||||
int i = 0;
|
||||
|
||||
fn = uses[i++];
|
||||
|
||||
newParams = new int[ params.length ];
|
||||
for(int j = 0; j < newParams.length; j++)
|
||||
newParams[j] = uses[i++];
|
||||
|
||||
if (lexicalReads != null) {
|
||||
reads = new Access[ lexicalReads.length ];
|
||||
for(int j = 0; j < reads.length; j++)
|
||||
reads[j] = new Access(lexicalReads[j].variableName, lexicalReads[j].variableDefiner, uses[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
int newLval = result;
|
||||
int newExp = exception;
|
||||
Access[] writes = lexicalWrites;
|
||||
|
||||
if (defs != null) {
|
||||
int i = 0;
|
||||
newLval = defs[i++];
|
||||
newExp = defs[i++];
|
||||
|
||||
if (lexicalWrites != null) {
|
||||
writes = new Access[ lexicalWrites.length ];
|
||||
for(int j = 0; j < writes.length; j++)
|
||||
writes[j] = new Access(lexicalWrites[j].variableName, lexicalWrites[j].variableDefiner, defs[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
return new JavaScriptInvoke(fn, newLval, newParams, newExp, site, reads, writes);
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||
StringBuffer s = new StringBuffer();
|
||||
if (result != -1) {
|
||||
s.append(getValueString(symbolTable, d, result)).append(" = ");
|
||||
}
|
||||
if (site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference))
|
||||
s.append("construct ");
|
||||
else
|
||||
s.append("invoke ");
|
||||
s.append(getValueString(symbolTable, d, function));
|
||||
|
||||
if (site != null) s.append("@").append(site.getProgramCounter());
|
||||
|
||||
if (params != null) {
|
||||
if (params.length > 0) {
|
||||
s.append(" ").append(getValueString(symbolTable, d, params[0]));
|
||||
}
|
||||
for (int i = 1; i < params.length; i++) {
|
||||
s.append(",").append(getValueString(symbolTable, d, params[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (exception == -1) {
|
||||
s.append(" exception: NOT MODELED");
|
||||
} else {
|
||||
s.append(" exception:").append(getValueString(symbolTable, d, exception));
|
||||
}
|
||||
|
||||
if (lexicalReads != null) {
|
||||
s.append(" (reads:");
|
||||
for(int i = 0; i < lexicalReads.length; i++) {
|
||||
s.append(" ").append(lexicalReads[i].variableName).append(":").append( getValueString(symbolTable, d, lexicalReads[i].valueNumber) );
|
||||
}
|
||||
s.append(")");
|
||||
}
|
||||
|
||||
if (lexicalWrites != null) {
|
||||
s.append(" (writes:");
|
||||
for(int i = 0; i < lexicalWrites.length; i++) {
|
||||
s.append(" ").append(lexicalWrites[i].variableName).append(":").append( getValueString(symbolTable, d, lexicalWrites[i].valueNumber) );
|
||||
}
|
||||
s.append(")");
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.domo.ssa.Instruction#visit(Visitor)
|
||||
*/
|
||||
public void visit(IVisitor v) {
|
||||
Assertions._assert(v instanceof InstructionVisitor);
|
||||
((InstructionVisitor)v).visitJavaScriptInvoke(this);
|
||||
}
|
||||
|
||||
public int getNumberOfParameters() {
|
||||
if (params == null) {
|
||||
return 1;
|
||||
} else {
|
||||
return params.length+1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.domo.ssa.Instruction#getUse(int)
|
||||
*/
|
||||
public int getUse(int j) {
|
||||
if (j == 0)
|
||||
return function;
|
||||
else if (j <= params.length)
|
||||
return params[j-1];
|
||||
else {
|
||||
return super.getUse(j);
|
||||
}
|
||||
}
|
||||
|
||||
public int getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
|
||||
*/
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.typeErrorExceptions();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return site.hashCode() * function * 7529;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof JavaScriptInvoke) {
|
||||
JavaScriptInvoke other = (JavaScriptInvoke)obj;
|
||||
if (site.equals(other.site)) {
|
||||
if (getNumberOfUses() == other.getNumberOfUses()) {
|
||||
for(int i = 0; i < getNumberOfUses(); i++) {
|
||||
if (getUse(i) != other.getUse(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (getNumberOfDefs() == other.getNumberOfDefs()) {
|
||||
for(int i = 0; i < getNumberOfDefs(); i++) {
|
||||
if (getDef(i) != other.getDef(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.ssa.*;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class JavaScriptNewInstruction extends SSANewInstruction {
|
||||
|
||||
public JavaScriptNewInstruction(int result, NewSiteReference site) {
|
||||
super(result, site);
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return
|
||||
new JavaScriptNewInstruction(
|
||||
defs==null? getDef(): defs[0],
|
||||
getNewSite());
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.typeErrorExceptions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaScriptPropertyRead extends AbstractReflectiveGet {
|
||||
public JavaScriptPropertyRead(int result, int objectRef, int memberRef) {
|
||||
super(result, objectRef, memberRef);
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return
|
||||
new JavaScriptPropertyRead(
|
||||
defs==null? getDef(): defs[0],
|
||||
uses==null? getObjectRef(): uses[0],
|
||||
uses==null? getMemberRef(): uses[1]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#isPEI()
|
||||
*/
|
||||
public boolean isPEI() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
|
||||
*/
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.typeErrorExceptions();
|
||||
}
|
||||
|
||||
/**
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.SSAInstruction#visit(com.ibm.domo.ssa.SSAInstruction.Visitor)
|
||||
*/
|
||||
public void visit(IVisitor v) {
|
||||
Assertions._assert(v instanceof InstructionVisitor);
|
||||
((InstructionVisitor)v).visitJavaScriptPropertyRead(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaScriptPropertyWrite extends AbstractReflectivePut {
|
||||
|
||||
public JavaScriptPropertyWrite(int objectRef, int memberRef, int value) {
|
||||
super(objectRef, memberRef, value);
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return
|
||||
new JavaScriptPropertyWrite(
|
||||
uses==null? getObjectRef(): uses[0],
|
||||
uses==null? getMemberRef(): uses[1],
|
||||
uses==null? getValue(): uses[2]);
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||
return super.toString(symbolTable, d) +
|
||||
" = " +
|
||||
getValueString(symbolTable, d, getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.domo.ssa.Instruction#visit(Visitor)
|
||||
*/
|
||||
public void visit(IVisitor v) {
|
||||
Assertions._assert(v instanceof InstructionVisitor);
|
||||
((InstructionVisitor)v).visitJavaScriptPropertyWrite(this);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#isPEI()
|
||||
*/
|
||||
public boolean isPEI() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
|
||||
*/
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.typeErrorExceptions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaScriptStaticPropertyRead extends SSAGetInstruction {
|
||||
|
||||
public JavaScriptStaticPropertyRead(int result,
|
||||
int objectRef,
|
||||
FieldReference memberRef) {
|
||||
super(result, objectRef, memberRef);
|
||||
}
|
||||
|
||||
public JavaScriptStaticPropertyRead(int result,
|
||||
int objectRef,
|
||||
String fieldName)
|
||||
{
|
||||
this(result,
|
||||
objectRef,
|
||||
FieldReference.findOrCreate(
|
||||
JavaScriptTypes.Root,
|
||||
Atom.findOrCreateUnicodeAtom(fieldName),
|
||||
JavaScriptTypes.Root));
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return
|
||||
new JavaScriptStaticPropertyRead(
|
||||
defs==null? getDef(): defs[0],
|
||||
uses==null? getRef(): uses[0],
|
||||
getDeclaredField());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
|
||||
*/
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.typeErrorExceptions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaScriptStaticPropertyWrite extends SSAPutInstruction {
|
||||
|
||||
public JavaScriptStaticPropertyWrite(int objectRef,
|
||||
FieldReference memberRef,
|
||||
int value) {
|
||||
super(objectRef, value, memberRef);
|
||||
}
|
||||
|
||||
public JavaScriptStaticPropertyWrite(int objectRef,
|
||||
String fieldName,
|
||||
int value)
|
||||
{
|
||||
this(objectRef,
|
||||
FieldReference.findOrCreate(
|
||||
JavaScriptTypes.Root,
|
||||
Atom.findOrCreateUnicodeAtom(fieldName),
|
||||
JavaScriptTypes.Root),
|
||||
value);
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return
|
||||
new JavaScriptStaticPropertyWrite(
|
||||
uses==null? getRef(): uses[0],
|
||||
getDeclaredField(),
|
||||
uses==null? getVal(): uses[1]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
|
||||
*/
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.typeErrorExceptions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.ssa.SSAAbstractUnaryInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.ValueDecorator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class JavaScriptTypeOfInstruction extends SSAAbstractUnaryInstruction {
|
||||
|
||||
public JavaScriptTypeOfInstruction(int lval, int object) {
|
||||
super(lval, object);
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return new JavaScriptTypeOfInstruction((defs != null ? defs[0] : getDef(0)), (uses != null ? uses[0] : getUse(0)));
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||
return getValueString(symbolTable, d, getDef(0)) + " = typeof(" + getValueString(symbolTable, d, getUse(0)) + ")";
|
||||
}
|
||||
|
||||
public void visit(IVisitor v) {
|
||||
((InstructionVisitor) v).visitTypeOf(this);
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return Util.noExceptions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.ssa;
|
||||
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class Util {
|
||||
private static final Collection TYPE_ERROR_EXCEPTIONS =
|
||||
Collections.unmodifiableCollection(
|
||||
Collections.singleton( JavaScriptTypes.TypeError ));
|
||||
|
||||
|
||||
public static Collection typeErrorExceptions() {
|
||||
return TYPE_ERROR_EXCEPTIONS;
|
||||
}
|
||||
|
||||
public static Collection noExceptions() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.translator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
|
||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
||||
import com.ibm.wala.cast.tree.impl.CAstImpl;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
|
||||
public class CAstRhinoTranslator extends TranslatorBase {
|
||||
private final JSAstTranslator CAstToIR;
|
||||
|
||||
public void translate(ModuleEntry M, String N) throws IOException {
|
||||
CAstToIR.translate(
|
||||
new RhinoToAstTranslator(new CAstImpl(), M, N).translate(),
|
||||
N);
|
||||
}
|
||||
|
||||
public CAstRhinoTranslator(JavaScriptLoader loader) {
|
||||
this.CAstToIR = new JSAstTranslator(loader);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.translator;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.cast.ir.translator.*;
|
||||
import com.ibm.wala.cast.js.loader.*;
|
||||
import com.ibm.wala.cast.js.ssa.*;
|
||||
import com.ibm.wala.cast.js.types.*;
|
||||
import com.ibm.wala.cast.loader.AstMethod.*;
|
||||
import com.ibm.wala.cast.tree.*;
|
||||
import com.ibm.wala.cast.tree.visit.*;
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.cfg.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
|
||||
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
|
||||
|
||||
public class JSAstTranslator extends AstTranslator {
|
||||
private final static boolean DEBUG = true;
|
||||
|
||||
public JSAstTranslator(JavaScriptLoader loader) {
|
||||
super(loader);
|
||||
}
|
||||
|
||||
protected boolean hasImplicitGlobals() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean treatGlobalsAsLexicallyScoped() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean useLocalValuesForLexicalVars() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected TypeReference defaultCatchType() {
|
||||
return JavaScriptTypes.Root;
|
||||
}
|
||||
|
||||
protected TypeReference makeType(CAstType type) {
|
||||
Assertions.UNREACHABLE("JavaScript does not use CAstType");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void defineType(CAstEntity type, WalkContext wc) {
|
||||
Assertions.UNREACHABLE("JavaScript doesn't have types. I suggest you look elsewhere for your amusement.");
|
||||
}
|
||||
|
||||
protected void defineField(CAstEntity topEntity, WalkContext wc, CAstEntity n) {
|
||||
Assertions.UNREACHABLE("JavaScript doesn't have fields, numb-nuts!");
|
||||
}
|
||||
|
||||
protected String composeEntityName(WalkContext parent, CAstEntity f) {
|
||||
if (f.getKind() == CAstEntity.SCRIPT_ENTITY)
|
||||
return f.getName();
|
||||
else
|
||||
return parent.getName() + "/" + f.getName();
|
||||
}
|
||||
|
||||
protected void declareFunction(CAstEntity N, WalkContext context) {
|
||||
String fileName = context.file();
|
||||
String fnName = composeEntityName(context, N);
|
||||
if (N.getKind() == CAstEntity.SCRIPT_ENTITY) {
|
||||
((JavaScriptLoader)loader).defineScriptType("L"+fnName, N.getPosition());
|
||||
} else if (N.getKind() == CAstEntity.FUNCTION_ENTITY) {
|
||||
((JavaScriptLoader)loader).defineFunctionType("L"+fnName, N.getPosition());
|
||||
} else {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
protected void defineFunction(CAstEntity N,
|
||||
WalkContext definingContext,
|
||||
AbstractCFG cfg,
|
||||
SymbolTable symtab,
|
||||
boolean hasCatchBlock,
|
||||
TypeReference[][] caughtTypes,
|
||||
LexicalInformation LI,
|
||||
DebuggingInformation debugInfo)
|
||||
{
|
||||
if (DEBUG) Trace.println("\n\nAdding code for " + N);
|
||||
String fnName = composeEntityName(definingContext, N);
|
||||
|
||||
if (DEBUG) Trace.println( cfg );
|
||||
|
||||
((JavaScriptLoader)loader).defineCodeBodyCode("L"+fnName,
|
||||
cfg,
|
||||
symtab,
|
||||
hasCatchBlock,
|
||||
caughtTypes,
|
||||
LI,
|
||||
debugInfo);
|
||||
}
|
||||
|
||||
protected void doThrow(WalkContext context, int exception) {
|
||||
context.cfg().addInstruction(new NonExceptingThrowInstruction(exception));
|
||||
}
|
||||
|
||||
protected void doCall(WalkContext context, CAstNode call, int result, int exception, CAstNode name, int receiver, int[] arguments) {
|
||||
MethodReference ref =
|
||||
name.getValue().equals("ctor")?
|
||||
JavaScriptMethods.ctorReference:
|
||||
AstMethodReference.fnReference(JavaScriptTypes.CodeBody);
|
||||
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptInvoke(receiver, result, arguments, exception,
|
||||
new JSCallSiteReference(ref, context.cfg().getCurrentInstruction())));
|
||||
|
||||
context.cfg().addPreNode(call, context.getUnwindState());
|
||||
|
||||
context.cfg().newBlock( true );
|
||||
|
||||
if (context.getControlFlow().getTarget(call, null) != null)
|
||||
context.cfg().addPreEdge(call, context.getControlFlow().getTarget(call, null), true);
|
||||
else
|
||||
context.cfg().addPreEdgeToExit( call, true );
|
||||
}
|
||||
|
||||
protected void doNewObject(WalkContext context, CAstNode newNode, int result, Object type, int[] arguments) {
|
||||
Assertions._assert(arguments == null);
|
||||
TypeReference typeRef =
|
||||
TypeReference.findOrCreate(
|
||||
JavaScriptTypes.jsLoader,
|
||||
TypeName.string2TypeName( "L" + type ));
|
||||
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptNewInstruction(
|
||||
result,
|
||||
NewSiteReference.make(
|
||||
context.cfg().getCurrentInstruction(),
|
||||
typeRef)));
|
||||
}
|
||||
|
||||
protected void doMaterializeFunction(WalkContext context, int result, int exception, CAstEntity fn) {
|
||||
int nm = context.currentScope().getConstantValue("L"+composeEntityName(context, fn));
|
||||
int tmp = doGlobalRead(context, "Function");
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptInvoke(tmp, result, new int[]{ nm }, exception,
|
||||
new JSCallSiteReference(
|
||||
JavaScriptMethods.ctorReference,
|
||||
context.cfg().getCurrentInstruction())));
|
||||
}
|
||||
|
||||
protected void doArrayRead(WalkContext context, int result, int arrayValue, CAstNode arrayRef, int[] dimValues) {
|
||||
Assertions.UNREACHABLE("JSAstTranslator.doArrayRead() called!");
|
||||
}
|
||||
|
||||
protected void doArrayWrite(WalkContext context, int arrayValue, CAstNode arrayRef, int[] dimValues, int rval) {
|
||||
Assertions.UNREACHABLE("JSAstTranslator.doArrayWrite() called!");
|
||||
}
|
||||
|
||||
protected void doFieldRead(WalkContext context, int result, int receiver, CAstNode elt, CAstNode parent) {
|
||||
walkNodes(elt, context);
|
||||
int x = context.currentScope().allocateTempValue();
|
||||
|
||||
context.cfg().addInstruction(new AssignInstruction(x, receiver));
|
||||
|
||||
int u = doGlobalRead(context, "undefined");
|
||||
context.cfg().newBlock( true );
|
||||
PreBasicBlock iterB = context.cfg().getCurrentBlock();
|
||||
|
||||
if (elt.getKind() == CAstNode.CONSTANT && elt.getValue() instanceof String)
|
||||
{
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptStaticPropertyRead(result, x, (String)elt.getValue() ));
|
||||
} else {
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptPropertyRead(result, x, getValue(elt) ));
|
||||
}
|
||||
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptStaticPropertyRead(x, x, "prototype"));
|
||||
|
||||
context.cfg().addInstruction(
|
||||
SSAInstructionFactory.ConditionalBranchInstruction(
|
||||
ConditionalBranchInstruction.Operator.EQ, null, result, u));
|
||||
|
||||
context.cfg().addEdge(iterB, iterB);
|
||||
context.cfg().newBlock( true );
|
||||
}
|
||||
|
||||
protected void doFieldWrite(WalkContext context, int receiver, CAstNode elt, CAstNode parent, int rval) {
|
||||
walkNodes(elt, context);
|
||||
if (elt.getKind() == CAstNode.CONSTANT && elt.getValue() instanceof String)
|
||||
{
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptStaticPropertyWrite(receiver, (String)elt.getValue(), rval));
|
||||
} else {
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptPropertyWrite(receiver, getValue(elt), rval));
|
||||
}
|
||||
}
|
||||
|
||||
protected void doPrimitive(int resultVal, WalkContext context, CAstNode primitiveCall) {
|
||||
try {
|
||||
String name = (String)primitiveCall.getChild(0).getValue();
|
||||
if (name.equals("GlobalNaN")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Float(Float.NaN))));
|
||||
} else if (name.equals("GlobalInfinity")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Float(Float.POSITIVE_INFINITY))));
|
||||
} else if (name.equals("MathE")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Double(Math.E))));
|
||||
} else if (name.equals("MathPI")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Double(Math.PI))));
|
||||
} else if (name.equals("MathSQRT1_2")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Double(Math.sqrt(.5)))));
|
||||
} else if (name.equals("MathSQRT2")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Double(Math.sqrt(2)))));
|
||||
} else if (name.equals("MathLN2")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Double(Math.log(2)))));
|
||||
} else if (name.equals("MathLN10")) {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue(new Double(Math.log(10)))));
|
||||
} else if (name.equals("NewObject")) {
|
||||
doNewObject(context, null, resultVal, "Object", null);
|
||||
|
||||
} else if (name.equals("NewArray")) {
|
||||
doNewObject(context, null, resultVal, "Array", null);
|
||||
|
||||
} else if (name.equals("NewString")) {
|
||||
doNewObject(context, null, resultVal, "String", null);
|
||||
|
||||
} else if (name.equals("NewNumber")) {
|
||||
doNewObject(context, null, resultVal, "Number", null);
|
||||
|
||||
} else if (name.equals("NewRegExp")) {
|
||||
doNewObject(context, null, resultVal, "RegExp", null);
|
||||
|
||||
} else if (name.equals("NewFunction")) {
|
||||
doNewObject(context, null, resultVal, "Function", null);
|
||||
|
||||
} else if (name.equals("NewUndefined")) {
|
||||
doNewObject(context, null, resultVal, "Undefined", null);
|
||||
|
||||
} else {
|
||||
context.cfg().addInstruction(
|
||||
new AssignInstruction(
|
||||
resultVal,
|
||||
context.currentScope().getConstantValue( null )));
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
throw new RuntimeException("Cannot translate primitive " + primitiveCall.getChild(0).getValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean doVisit(CAstNode n, Context cntxt, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext)cntxt;
|
||||
switch (n.getKind()) {
|
||||
case CAstNode.TYPE_OF: {
|
||||
int result = context.currentScope().allocateTempValue();
|
||||
|
||||
walkNodes(n.getChild(0), context);
|
||||
int ref = getValue(n.getChild(0));
|
||||
|
||||
context.cfg().addInstruction(
|
||||
new JavaScriptTypeOfInstruction(result, ref));
|
||||
|
||||
setValue(n, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.translator;
|
||||
|
||||
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
|
||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
||||
|
||||
public interface JavaScriptTranslatorFactory {
|
||||
|
||||
TranslatorToIR make(JavaScriptLoader loader);
|
||||
|
||||
public static class CAstRhinoFactory implements JavaScriptTranslatorFactory {
|
||||
|
||||
public TranslatorToIR make(JavaScriptLoader loader) {
|
||||
return new CAstRhinoTranslator(loader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,56 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.translator;
|
||||
|
||||
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class TranslatorBase implements TranslatorToIR {
|
||||
|
||||
protected static final Set bootstrapFileNames;
|
||||
|
||||
private static String prologueFileName = "prologue.js";
|
||||
|
||||
public static void resetPrologueFile() {
|
||||
prologueFileName = "prologue.js";
|
||||
}
|
||||
|
||||
public static void setPrologueFile(String name) {
|
||||
prologueFileName = name;
|
||||
}
|
||||
|
||||
public static void addBootstrapFile(String fileName) {
|
||||
bootstrapFileNames.add( fileName );
|
||||
}
|
||||
|
||||
static {
|
||||
bootstrapFileNames = new HashSet();
|
||||
bootstrapFileNames.add( prologueFileName );
|
||||
}
|
||||
|
||||
public abstract void translate(ModuleEntry M, String N) throws IOException;
|
||||
|
||||
public void translate(Set modules) throws IOException {
|
||||
translate(new SourceURLModule(getClass().getClassLoader().getResource(prologueFileName)), prologueFileName);
|
||||
Iterator MS = modules.iterator();
|
||||
while (MS.hasNext()) {
|
||||
ModuleEntry M = (ModuleEntry) MS.next();
|
||||
if (M instanceof SourceFileModule) {
|
||||
translate(M, ((SourceFileModule)M).getClassName());
|
||||
} else {
|
||||
translate(M, M.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.types;
|
||||
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
||||
public class JavaScriptMethods extends AstMethodReference {
|
||||
|
||||
public final static String ctorAtomStr = "ctor";
|
||||
public final static Atom ctorAtom = Atom.findOrCreateUnicodeAtom(ctorAtomStr);
|
||||
public final static String ctorDescStr = "()LRoot;";
|
||||
public final static Descriptor ctorDesc = Descriptor.findOrCreateUTF8(ctorDescStr);
|
||||
public final static MethodReference ctorReference =
|
||||
MethodReference.findOrCreate(JavaScriptTypes.CodeBody, ctorAtom, ctorDesc);
|
||||
|
||||
public static MethodReference makeCtorReference(TypeReference cls) {
|
||||
return MethodReference.findOrCreate(cls, ctorAtom, ctorDesc);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.types;
|
||||
|
||||
import com.ibm.wala.cast.types.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
||||
public class JavaScriptTypes extends AstTypeReference {
|
||||
|
||||
public static final String jsLoaderNameStr = "JavaScript";
|
||||
|
||||
public static final Atom jsLoaderName =
|
||||
Atom.findOrCreateUnicodeAtom(jsLoaderNameStr);
|
||||
|
||||
public static final ClassLoaderReference jsLoader =
|
||||
new ClassLoaderReference( jsLoaderName );
|
||||
|
||||
public static final TypeReference Root =
|
||||
TypeReference.findOrCreate(jsLoader, rootTypeName);
|
||||
|
||||
public static final TypeReference Undefined =
|
||||
TypeReference.findOrCreate(jsLoader, "LUndefined");
|
||||
|
||||
public static final TypeReference Null =
|
||||
TypeReference.findOrCreate(jsLoader, "LNull");
|
||||
|
||||
public static final TypeReference Boolean =
|
||||
TypeReference.findOrCreate(jsLoader, "LBoolean");
|
||||
|
||||
public static final TypeReference String =
|
||||
TypeReference.findOrCreate(jsLoader, "LString");
|
||||
|
||||
public static final TypeReference Number =
|
||||
TypeReference.findOrCreate(jsLoader, "LNumber");
|
||||
|
||||
public static final TypeReference Date =
|
||||
TypeReference.findOrCreate(jsLoader, "LDate");
|
||||
|
||||
public static final TypeReference RegExp =
|
||||
TypeReference.findOrCreate(jsLoader, "LRegExp");
|
||||
|
||||
public static final TypeReference Array =
|
||||
TypeReference.findOrCreate(jsLoader, "LArray");
|
||||
|
||||
public static final TypeReference Object =
|
||||
TypeReference.findOrCreate(jsLoader, "LObject");
|
||||
|
||||
public static final TypeReference CodeBody =
|
||||
TypeReference.findOrCreate(jsLoader, functionTypeName);
|
||||
|
||||
public static final TypeReference Function =
|
||||
TypeReference.findOrCreate(jsLoader, "LFunction");
|
||||
|
||||
public static final TypeReference Script =
|
||||
TypeReference.findOrCreate(jsLoader, "LScript");
|
||||
|
||||
public static final TypeReference TypeError =
|
||||
TypeReference.findOrCreate(jsLoader, "LTypeError");
|
||||
|
||||
public static final TypeReference Primitives =
|
||||
TypeReference.findOrCreate(jsLoader, "LPrimitives");
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
import javax.swing.text.html.*;
|
||||
import javax.swing.text.html.parser.*;
|
||||
|
||||
public class Generator {
|
||||
public static final String preamble = "preamble.js", temp = "temp.js";
|
||||
|
||||
public static interface CallbackFactory {
|
||||
HTMLEditorKit.ParserCallback createCallback(URL input, FileWriter out, FileWriter out2);
|
||||
}
|
||||
|
||||
public static class HTMLCallbackFactory implements CallbackFactory {
|
||||
public HTMLEditorKit.ParserCallback createCallback(URL input, FileWriter out, FileWriter out2) {
|
||||
return new HTMLCallback(input, out, out2);
|
||||
}
|
||||
}
|
||||
|
||||
public static final CallbackFactory defaultCallbackFactory = new HTMLCallbackFactory();
|
||||
|
||||
private CallbackFactory callbackFactory;
|
||||
private boolean ignoreCharset;
|
||||
|
||||
public Generator(boolean ignoreCharset, CallbackFactory factory) {
|
||||
this.ignoreCharset = ignoreCharset;
|
||||
this.callbackFactory = factory;
|
||||
}
|
||||
|
||||
public Generator() {
|
||||
this(false, defaultCallbackFactory);
|
||||
}
|
||||
|
||||
private InputStreamReader getStream(String url) throws IOException {
|
||||
return getStream( Generator.class.getClassLoader().getResource( url ) );
|
||||
}
|
||||
|
||||
private InputStreamReader getStream(URL url) throws IOException {
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(false);
|
||||
conn.setUseCaches(false);
|
||||
|
||||
return new InputStreamReader(conn.getInputStream());
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws IOException {
|
||||
Generator g = new Generator();
|
||||
if (new File(args[0]).exists()) {
|
||||
g.generate(new URL("file:" + args[0]), new File(args[1]));
|
||||
}
|
||||
}
|
||||
|
||||
public void generate(URL input, File outFile) throws IOException {
|
||||
InputStreamReader fr = getStream( input );
|
||||
FileWriter out = new FileWriter(outFile);
|
||||
FileWriter out2 = new FileWriter(temp);
|
||||
|
||||
ParserDelegator pd = new ParserDelegator();
|
||||
HTMLEditorKit.ParserCallback cb = callbackFactory.createCallback(input, out, out2);
|
||||
|
||||
generatePreamble(out, cb);
|
||||
|
||||
out.write("//Generation of the DOM Tree Begins\n");
|
||||
pd.parse(fr, cb, ignoreCharset);
|
||||
out2.close();
|
||||
out.write("//Generation of the DOM Tree Ends\n\n\n");
|
||||
|
||||
FileReader tmp = new FileReader(temp);
|
||||
BufferedReader tempIn = new BufferedReader(tmp);
|
||||
out.write("//Embedded Script Region Begins\n");
|
||||
String line = tempIn.readLine();
|
||||
while(line != null) {
|
||||
out.write(line+"\n");
|
||||
line = tempIn.readLine();
|
||||
}
|
||||
out.write("//Embedded Script Region Ends\n\n\n");
|
||||
|
||||
generateTrailer(out, cb);
|
||||
|
||||
out.close();
|
||||
}
|
||||
|
||||
protected void generatePreamble(FileWriter out, HTMLEditorKit.ParserCallback cb) throws IOException {
|
||||
InputStreamReader pm = getStream( preamble );
|
||||
BufferedReader pmIn = new BufferedReader(pm);
|
||||
|
||||
out.write("//Preamble Begin\n");
|
||||
String line = pmIn.readLine();
|
||||
while(line != null) {
|
||||
out.write(line+"\n");
|
||||
line = pmIn.readLine();
|
||||
}
|
||||
out.write("//Preamble End\n\n\n");
|
||||
}
|
||||
|
||||
protected void generateTrailer(FileWriter out, HTMLEditorKit.ParserCallback cb) throws IOException {
|
||||
out.write("//Trailer Begin\n");
|
||||
out.write("//Trailer End\n");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import javax.swing.text.html.*;
|
||||
import javax.swing.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class HTMLCallback extends HTMLEditorKit.ParserCallback {
|
||||
private final URL input;
|
||||
private final FileWriter out, out2;
|
||||
|
||||
private int counter=0;
|
||||
private boolean script = false;
|
||||
|
||||
private final HashMap constructors = new HashMap();
|
||||
|
||||
protected final Stack stack;
|
||||
|
||||
public HTMLCallback(URL input, FileWriter out, FileWriter out2) {
|
||||
this.input = input;
|
||||
this.out = out;
|
||||
this.out2 = out2;
|
||||
stack = new Stack();
|
||||
constructors.put("FORM", "DOMHTMLFormElement");
|
||||
constructors.put("TABLE", "DOMHTMLTableElement");
|
||||
}
|
||||
|
||||
protected FileWriter getWriter() {
|
||||
return out;
|
||||
}
|
||||
|
||||
protected FileWriter getWriter2() {
|
||||
return out2;
|
||||
}
|
||||
|
||||
public void flush() throws BadLocationException {
|
||||
|
||||
}
|
||||
|
||||
public void handleText(char[] data, int pos) {
|
||||
getScript(data);
|
||||
}
|
||||
|
||||
private void getScript(char [] data) {
|
||||
if(script) {
|
||||
System.out.print(data);
|
||||
try {
|
||||
out2.write(data);
|
||||
out2.write("\n");
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error writing to second file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleComment(char[] data, int pos) {
|
||||
getScript(data);
|
||||
}
|
||||
|
||||
protected String createElement(HTML.Tag t, MutableAttributeSet a) {
|
||||
String tag = t.toString().toUpperCase();
|
||||
String varName = "node" + (counter++);
|
||||
String cons = (String)constructors.get(tag);
|
||||
if(tag.equals("SCRIPT")) {
|
||||
Object value = a.getAttribute( HTML.Attribute.SRC );
|
||||
|
||||
// script is out-of-line
|
||||
if (value != null) {
|
||||
try {
|
||||
URL scriptSrc = new URL(input, value.toString());
|
||||
InputStreamReader scriptReader =
|
||||
new InputStreamReader(
|
||||
scriptSrc.openConnection().getInputStream());
|
||||
|
||||
int read;
|
||||
char[] buffer = new char[ 1024 ];
|
||||
while ( (read = scriptReader.read(buffer)) != -1 ) {
|
||||
out2.write(buffer, 0, read);
|
||||
}
|
||||
scriptReader.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("bad input script " + value);
|
||||
}
|
||||
|
||||
// script is inline
|
||||
} else {
|
||||
System.out.println("Entering Script");
|
||||
script = true;
|
||||
}
|
||||
}
|
||||
if(cons == null) cons = "DOMHTMLElement";
|
||||
try {
|
||||
writeElement(t, a, tag, cons, varName);
|
||||
Enumeration enu = a.getAttributeNames();
|
||||
while(enu.hasMoreElements()) {
|
||||
Object attrObj = enu.nextElement();
|
||||
String attr = attrObj.toString();
|
||||
String value = a.getAttribute(attrObj).toString();
|
||||
System.out.println(attr);
|
||||
writeAttribute(t, a, attr, value, varName);
|
||||
}
|
||||
out.write("\n");
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error writing to file");
|
||||
System.exit(1);
|
||||
}
|
||||
return varName;
|
||||
}
|
||||
|
||||
protected void writeElement(HTML.Tag t, MutableAttributeSet a, String tag, String cons, String varName) throws IOException {
|
||||
out.write("var " + varName + " = new " + cons + "(" + tag + ");\n");
|
||||
if(!stack.empty()) {
|
||||
out.write(stack.peek() + ".appendChild(" + varName + ");\n");
|
||||
} else {
|
||||
out.write("document.appendChild(" + varName + ");\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeAttribute(HTML.Tag t, MutableAttributeSet a, String attr, String value, String varName) throws IOException {
|
||||
writePortletAttribute(t, a, attr, value, varName);
|
||||
writeEventAttribute(t, a, attr, value, varName);
|
||||
}
|
||||
|
||||
protected void writeEventAttribute(HTML.Tag t, MutableAttributeSet a, String attr, String value, String varName) throws IOException {
|
||||
if(attr.substring(0,2).equals("on")) {
|
||||
out.write(varName + "." + attr + " = function " + attr + "_" + varName + "(event) {" + value + "};\n");
|
||||
out2.write("\n\n" + varName + "." + attr + "(null);\n\n");
|
||||
} else {
|
||||
out.write(varName + ".setAttribute('" + attr + "', '" + value + "');\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected void writePortletAttribute(HTML.Tag t, MutableAttributeSet a, String attr, String value, String varName) throws IOException {
|
||||
if(attr.equals("portletid")) {
|
||||
if(value.substring(value.length()-4).equals("vice")) {
|
||||
out.write("\n\nfunction cVice() { var contextVice = " + varName + "; }\ncVice();\n\n");
|
||||
} else if(value.substring(value.length()-4).equals("root")) {
|
||||
out.write("\n\nfunction cRoot() { var contextRoot = " + varName + "; }\ncRoot();\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
|
||||
System.out.println("Start" + t);
|
||||
String varName = createElement(t,a);
|
||||
stack.push(varName);
|
||||
}
|
||||
|
||||
public void handleEndTag(HTML.Tag t, int pos) {
|
||||
if(t.toString().toUpperCase().equals("SCRIPT")) {
|
||||
System.out.println("Exiting Script");
|
||||
script = false;
|
||||
}
|
||||
System.out.println("End" + t);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
|
||||
System.out.println("Simple" + t);
|
||||
createElement(t,a);
|
||||
}
|
||||
|
||||
public void handleError(String errorMsg, int pos) {
|
||||
System.out.println("Error" + errorMsg);
|
||||
}
|
||||
|
||||
public void handleEndOfLineString(String eol) {
|
||||
System.out.println("EOL");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.js.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.classLoader.SourceFileModule;
|
||||
import com.ibm.wala.util.warnings.*;
|
||||
|
||||
public class WebUtil {
|
||||
private static final String outputDir;
|
||||
private static final Generator defaultGenerator = new Generator();
|
||||
|
||||
static {
|
||||
String dir = System.getProperty("java.io.tmpdir");
|
||||
if (! dir.endsWith(File.separator))
|
||||
dir = dir + File.separator;
|
||||
|
||||
outputDir = dir;
|
||||
}
|
||||
|
||||
public static SourceFileModule extractScriptFromHTML(URL url) {
|
||||
return extractScriptFromHTML(url, defaultGenerator);
|
||||
}
|
||||
|
||||
public static SourceFileModule extractScriptFromHTML(URL url, Generator generator) {
|
||||
try {
|
||||
String urlFile = url.getFile();
|
||||
String urlName = urlFile.substring(urlFile.lastIndexOf('/'));
|
||||
File F = new File(outputDir + urlName);
|
||||
Trace.println("making driver at " + F + " " + outputDir);
|
||||
if (F.exists()) F.delete();
|
||||
|
||||
generator.generate(url, F);
|
||||
|
||||
return new SourceFileModule(F, urlName.substring(1));
|
||||
|
||||
} catch (IOException e) {
|
||||
Assertions.UNREACHABLE("error processing " + url + ": " + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.JSZeroXCFABuilder;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.Util;
|
||||
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoints;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
class dumpCallGraph {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
WarningSet warnings = new WarningSet();
|
||||
|
||||
JavaScriptLoaderFactory loaders = Util.makeLoaders();
|
||||
AnalysisScope scope = Util.makeScope( args, loaders );
|
||||
ClassHierarchy cha = Util.makeHierarchy( scope, loaders, warnings );
|
||||
Entrypoints roots = Util.makeScriptRoots( cha );
|
||||
AnalysisOptions options = Util.makeOptions(scope, false, cha, roots, warnings);
|
||||
|
||||
JSCFABuilder builder = new JSZeroXCFABuilder(cha, warnings, options, null, null, null, ZeroXInstanceKeys.ALLOCATIONS);
|
||||
|
||||
CallGraph cg = builder.makeCallGraph( options );
|
||||
|
||||
System.err.println( cg );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
import java.io.FileReader;
|
||||
|
||||
import org.mozilla.javascript.CompilerEnvirons;
|
||||
import org.mozilla.javascript.Parser;
|
||||
import org.mozilla.javascript.ScriptOrFnNode;
|
||||
import org.mozilla.javascript.tools.ToolErrorReporter;
|
||||
|
||||
class dumpRhinoParse {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
ToolErrorReporter reporter = new ToolErrorReporter(true);
|
||||
CompilerEnvirons compilerEnv = new CompilerEnvirons();
|
||||
compilerEnv.setErrorReporter(reporter);
|
||||
|
||||
Parser P = new Parser(compilerEnv, compilerEnv.getErrorReporter());
|
||||
|
||||
ScriptOrFnNode N = P.parse(new FileReader(args[0]), args[0], 1);
|
||||
System.out.println( N.toStringTree(N) );
|
||||
System.out.println( P.getEncodedSource() );
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
System.err.println( e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,599 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*****************************************************************************/
|
||||
import java.io.FileReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mozilla.javascript.CompilerEnvirons;
|
||||
import org.mozilla.javascript.FunctionNode;
|
||||
import org.mozilla.javascript.Node;
|
||||
import org.mozilla.javascript.Parser;
|
||||
import org.mozilla.javascript.ScriptOrFnNode;
|
||||
import org.mozilla.javascript.Token;
|
||||
import org.mozilla.javascript.tools.ToolErrorReporter;
|
||||
|
||||
class walkRhinoTree {
|
||||
|
||||
private final Map results = new HashMap();
|
||||
|
||||
private int nextValue = 1;
|
||||
|
||||
private int nextValueNumber() {
|
||||
return nextValue++;
|
||||
}
|
||||
|
||||
private int setValue(Node n, int v) {
|
||||
results.put(n, new Integer(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
private int allocValue(Node n) {
|
||||
return setValue(n, nextValueNumber());
|
||||
}
|
||||
|
||||
private int getValue(Node n) {
|
||||
return ((Integer)results.get(n)).intValue();
|
||||
}
|
||||
|
||||
private interface Symbol {
|
||||
int valueNumber();
|
||||
boolean isParameter();
|
||||
}
|
||||
|
||||
private final static int TYPE_LOCAL = 1;
|
||||
private final static int TYPE_GLOBAL = 2;
|
||||
private final static int TYPE_SCRIPT = 3;
|
||||
private final static int TYPE_FUNCTION = 4;
|
||||
|
||||
private interface Scope {
|
||||
int type();
|
||||
void declare(String name);
|
||||
boolean contains(String name);
|
||||
Symbol lookup(String name);
|
||||
}
|
||||
|
||||
private static abstract class AbstractScope implements Scope {
|
||||
private final Scope parent;
|
||||
private final Map values = new HashMap();
|
||||
|
||||
public void declare(String nm) {
|
||||
if (! contains(nm)) {
|
||||
values.put(nm, makeSymbol(nm));
|
||||
}
|
||||
}
|
||||
|
||||
AbstractScope(Scope parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
abstract protected Symbol makeSymbol(String nm);
|
||||
|
||||
public Symbol lookup(String nm) {
|
||||
if (contains(nm))
|
||||
return (Symbol)values.get(nm);
|
||||
else
|
||||
return parent.lookup(nm);
|
||||
}
|
||||
|
||||
public boolean contains(String nm) {
|
||||
return values.containsKey(nm);
|
||||
}
|
||||
};
|
||||
|
||||
Scope makeScriptScope(final ScriptOrFnNode s, Scope parent) {
|
||||
return new AbstractScope(parent) {
|
||||
public int type() { return TYPE_SCRIPT; }
|
||||
|
||||
protected Symbol makeSymbol(final String nm) {
|
||||
final int v = nextValueNumber();
|
||||
return
|
||||
new Symbol() {
|
||||
public String toString() { return nm; }
|
||||
public int valueNumber() { return v; }
|
||||
public boolean isParameter() { return false; }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Scope makeLocalScope(Node s, Scope parent) {
|
||||
return new AbstractScope(parent) {
|
||||
public int type() { return TYPE_LOCAL; }
|
||||
|
||||
protected Symbol makeSymbol(final String nm) {
|
||||
final int v = nextValueNumber();
|
||||
return
|
||||
new Symbol() {
|
||||
public String toString() { return nm; }
|
||||
public int valueNumber() { return v; }
|
||||
public boolean isParameter() { return false; }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Scope makeFunctionScope(final FunctionNode f, Scope parent) {
|
||||
Scope s = new AbstractScope(parent) {
|
||||
public int type() { return TYPE_FUNCTION; }
|
||||
|
||||
protected Symbol makeSymbol(final String nm) {
|
||||
final int v = nextValueNumber();
|
||||
return
|
||||
new Symbol() {
|
||||
public String toString() { return nm; }
|
||||
public int valueNumber() { return v; }
|
||||
public boolean isParameter() {
|
||||
return f.getParamOrVarIndex(nm)<f.getParamCount();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
for(int i = 0; i < f.getParamCount(); i++)
|
||||
s.declare( f.getParamOrVarName(i) );
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
private static Scope makeGlobalScope() {
|
||||
return new Scope() {
|
||||
public int type() { return TYPE_GLOBAL; }
|
||||
|
||||
public void declare(String nm) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean contains(String nm) {
|
||||
return nm.equals("Math");
|
||||
}
|
||||
|
||||
public Symbol lookup(String nm) {
|
||||
return new Symbol() {
|
||||
public String toString() { return "Math"; }
|
||||
public int valueNumber() { return -1; }
|
||||
public boolean isParameter() { return false; }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private interface WalkContext {
|
||||
|
||||
ScriptOrFnNode top();
|
||||
|
||||
Scope scope();
|
||||
|
||||
boolean resultWanted();
|
||||
|
||||
Node getCatchFor(Object exceptionType);
|
||||
|
||||
Node getBreakFor(Object label);
|
||||
|
||||
Node getContinueFor(Object label);
|
||||
|
||||
Node getFinally();
|
||||
}
|
||||
|
||||
private abstract class DelegatingContext implements WalkContext {
|
||||
private final WalkContext parent;
|
||||
|
||||
DelegatingContext(WalkContext parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public ScriptOrFnNode top() { return parent.top(); }
|
||||
|
||||
public Scope scope() { return parent.scope(); }
|
||||
|
||||
public boolean resultWanted() { return parent.resultWanted(); }
|
||||
|
||||
public Node getCatchFor(Object l) { return parent.getCatchFor(l); }
|
||||
|
||||
public Node getBreakFor(Object l) { return parent.getBreakFor(l); }
|
||||
|
||||
public Node getContinueFor(Object l) { return parent.getContinueFor(l); }
|
||||
|
||||
public Node getFinally() { return parent.getFinally(); }
|
||||
|
||||
}
|
||||
|
||||
private class ScriptContext extends DelegatingContext {
|
||||
private final Scope scriptScope;
|
||||
|
||||
ScriptContext(WalkContext parent, Scope scriptScope) {
|
||||
super(parent);
|
||||
this.scriptScope = scriptScope;
|
||||
}
|
||||
|
||||
public Scope scope() { return scriptScope; }
|
||||
|
||||
}
|
||||
|
||||
private class LocalContext extends DelegatingContext {
|
||||
private final Scope localScope;
|
||||
|
||||
LocalContext(WalkContext parent, Scope localScope) {
|
||||
super(parent);
|
||||
this.localScope = localScope;
|
||||
}
|
||||
|
||||
public Scope scope() { return localScope; }
|
||||
|
||||
}
|
||||
|
||||
private class FunctionContext extends ScriptContext {
|
||||
private final ScriptOrFnNode topNode;
|
||||
|
||||
FunctionContext(WalkContext parent, Scope funScope, ScriptOrFnNode s) {
|
||||
super(parent, funScope);
|
||||
this.topNode = s;
|
||||
}
|
||||
|
||||
public ScriptOrFnNode top() { return topNode; }
|
||||
}
|
||||
|
||||
private class LoopContext extends DelegatingContext {
|
||||
private final Node breakTo;
|
||||
private final Node continueTo;
|
||||
|
||||
LoopContext(WalkContext parent, Node breakTo, Node continueTo) {
|
||||
super(parent);
|
||||
this.breakTo = breakTo;
|
||||
this.continueTo = continueTo;
|
||||
}
|
||||
|
||||
public Node getBreakFor(Object l) {
|
||||
return (l == null)? breakTo: super.getBreakFor(l);
|
||||
}
|
||||
|
||||
public Node getContinueFor(Object l) {
|
||||
return (l == null)? continueTo: super.getContinueFor(l);
|
||||
}
|
||||
}
|
||||
|
||||
private class TryCatchContext extends DelegatingContext {
|
||||
private final Node catchNode;
|
||||
private final Node finallyNode;
|
||||
|
||||
TryCatchContext(WalkContext parent, Node catchNode, Node finallyNode) {
|
||||
super(parent);
|
||||
this.catchNode = catchNode;
|
||||
this.finallyNode = finallyNode;
|
||||
}
|
||||
|
||||
public Node getCatchFor(Object l) { return catchNode; }
|
||||
|
||||
public Node getFinally() { return finallyNode; }
|
||||
}
|
||||
|
||||
private void walkNodes(final Node n, WalkContext context) {
|
||||
if (n instanceof ScriptOrFnNode) {
|
||||
WalkContext child;
|
||||
if (n instanceof FunctionNode) {
|
||||
FunctionNode f = (FunctionNode)n;
|
||||
System.err.println("function " + f.getFunctionName());
|
||||
child = new FunctionContext(context, makeFunctionScope(f, context.scope()), f);
|
||||
} else {
|
||||
ScriptOrFnNode s = (ScriptOrFnNode)n;
|
||||
System.err.println("program");
|
||||
child = new ScriptContext(context, makeScriptScope(s, context.scope()));
|
||||
}
|
||||
|
||||
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
|
||||
walkNodes(c, child);
|
||||
|
||||
} else {
|
||||
int NT = n.getType();
|
||||
switch (NT) {
|
||||
case Token.FUNCTION: {
|
||||
int fnIndex = n.getExistingIntProp(Node.FUNCTION_PROP);
|
||||
FunctionNode fn = context.top().getFunctionNode(fnIndex);
|
||||
|
||||
System.err.println("declaring " + fn.getFunctionName() );
|
||||
|
||||
context.scope().declare( fn.getFunctionName() );
|
||||
walkNodes(fn, context);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.LOOP: {
|
||||
Node contTo = ((Node.Jump)n).getContinue();
|
||||
Node breakTo = ((Node.Jump)n).target;
|
||||
WalkContext child = new LoopContext(context, breakTo, contTo);
|
||||
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
|
||||
walkNodes(c, child);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.LOCAL_BLOCK: {
|
||||
WalkContext child = new LocalContext(context, makeLocalScope(n, context.scope()));
|
||||
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
|
||||
walkNodes(c, child);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.CATCH_SCOPE: {
|
||||
Node id = n.getFirstChild();
|
||||
context.scope().declare( id.getString() );
|
||||
System.err.println( context.scope().lookup( id.getString() ).valueNumber() + " = caught exception");
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.TRY: {
|
||||
Node catchNode = ((Node.Jump)n).target;
|
||||
Node finallyNode = ((Node.Jump)n).getFinally();
|
||||
WalkContext child =
|
||||
new TryCatchContext(context, catchNode, finallyNode);
|
||||
|
||||
Node c = n.getFirstChild();
|
||||
for (; c != null; c = c.getNext()) {
|
||||
if (c.getType() == Token.FINALLY) break;
|
||||
walkNodes(c, child);
|
||||
}
|
||||
|
||||
for (; c != null; c = c.getNext()) {
|
||||
walkNodes(c, context);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.JSR: {
|
||||
Node jsrTarget = ((Node.Jump)n).target;
|
||||
Node finallyBlock = context.getFinally();
|
||||
if (jsrTarget != finallyBlock) throw new Error();
|
||||
Node finallyNode = jsrTarget.getNext();
|
||||
walkNodes(finallyNode, context);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.WITH:
|
||||
case Token.FINALLY:
|
||||
case Token.BLOCK:
|
||||
case Token.LABEL:
|
||||
case Token.EXPR_VOID: {
|
||||
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
|
||||
walkNodes(c, context);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.CALL: {
|
||||
int result = allocValue(n);
|
||||
Node callee = n.getFirstChild();
|
||||
|
||||
int fun;
|
||||
if (callee.getType() == Token.NAME)
|
||||
fun = context.scope().lookup( callee.getString() ).valueNumber();
|
||||
else {
|
||||
walkNodes( callee, context );
|
||||
fun = getValue( callee );
|
||||
}
|
||||
|
||||
int children = 0;
|
||||
for (Node c = callee.getNext(); c != null; c = c.getNext()) {
|
||||
walkNodes(c, context);
|
||||
children++;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int arguments[] = new int[ children ];
|
||||
for(Node arg = callee.getNext(); arg != null; arg = arg.getNext() )
|
||||
arguments[i++] = getValue( arg );
|
||||
|
||||
System.err.print(result + " = CALL " + fun);
|
||||
for(int j = 0; j < arguments.length; j++)
|
||||
System.err.print( " " + arguments[j] );
|
||||
System.err.print("\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.NAME: {
|
||||
setValue(n, context.scope().lookup( n.getString() ).valueNumber() );
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.STRING: {
|
||||
int result = allocValue(n);
|
||||
System.err.println(result + " = \"" + n.getString() + "\"");
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.NUMBER: {
|
||||
int result = allocValue(n);
|
||||
System.err.println(result + " = " + n.getDouble());
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.ADD:
|
||||
case Token.EQ:
|
||||
case Token.DIV:
|
||||
case Token.NE:
|
||||
case Token.GT:
|
||||
case Token.LT: {
|
||||
int result = allocValue(n);
|
||||
|
||||
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
|
||||
walkNodes(c, context);
|
||||
|
||||
Node l = n.getFirstChild();
|
||||
Node r = l.getNext();
|
||||
System.err.println(result + " = " + getValue(l) + " " + Token.name(NT) + " " + getValue(r));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.VAR: {
|
||||
Node nm = n.getFirstChild();
|
||||
context.scope().declare(nm.getString());
|
||||
if (nm.getFirstChild() != null) {
|
||||
walkNodes( nm.getFirstChild(), context );
|
||||
System.err.println(context.scope().lookup(nm.getString()) + " = " + getValue(nm.getFirstChild()) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.RETURN: {
|
||||
Node val = n.getFirstChild();
|
||||
if (val != null) {
|
||||
walkNodes(val, context);
|
||||
System.err.println("return " + getValue(val));
|
||||
} else {
|
||||
System.err.println("return");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.SETNAME: {
|
||||
Node nm = n.getFirstChild();
|
||||
walkNodes( nm.getNext(), context);
|
||||
System.err.println("set " + context.scope().lookup(nm.getString()).valueNumber() + "(" + nm.getString() + ") = " + getValue( nm.getNext() ));
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.IFNE:
|
||||
case Token.IFEQ: {
|
||||
Node expr = n.getFirstChild();
|
||||
walkNodes( expr, context );
|
||||
System.err.println(Token.name(NT) + " " + getValue(expr) + " GOTO " + ((Node.Jump)n).target);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.GOTO: {
|
||||
System.err.println("GOTO (" + Token.name(NT) + ") " + ((Node.Jump)n).target);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.BREAK: {
|
||||
System.err.println("GOTO (" + Token.name(NT) + ") " + ((Node.Jump)n).getJumpStatement().target);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.TARGET: {
|
||||
System.err.println("LABEL " + n);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.OR: {
|
||||
Object label = new Object() { public String toString() { return "OR:" + System.identityHashCode(n); } };
|
||||
Node l = n.getFirstChild();
|
||||
walkNodes(l, context);
|
||||
System.err.println(getValue(n) + " = " + getValue(l));
|
||||
System.err.println("IFEQ " + getValue(n) + " GOTO " + label);
|
||||
Node r = l.getNext();
|
||||
walkNodes(r, context);
|
||||
System.err.println(getValue(n) + " = " + getValue(r));
|
||||
System.err.println("LABEL " + label);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.INC: {
|
||||
int result = context.resultWanted()? allocValue(n): -1;
|
||||
Node l = n.getFirstChild();
|
||||
walkNodes(l, context);
|
||||
int flags = n.getIntProp( Node.INCRDECR_PROP, -1 );
|
||||
String op = ((flags&Node.DECR_FLAG)!=0)? "-": "+";
|
||||
if ((flags&Node.POST_FLAG)!=0) {
|
||||
if (context.resultWanted())
|
||||
System.err.println(result + " = " + getValue(l));
|
||||
System.err.println(getValue(l) + " = " + getValue(l) + " " + op + " 1");
|
||||
} else {
|
||||
System.err.println(getValue(l) + " = " + getValue(l) + " " + op + " 1");
|
||||
if (context.resultWanted())
|
||||
System.err.println(result + " = " + getValue(l));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.EMPTY:
|
||||
case Token.ENTERWITH:
|
||||
case Token.LEAVEWITH: {
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.GETPROP:
|
||||
case Token.GETELEM: {
|
||||
int result = allocValue(n);
|
||||
Node receiver = n.getFirstChild();
|
||||
walkNodes(receiver, context);
|
||||
|
||||
Node elt = receiver.getNext();
|
||||
if (elt.getType() == Token.STRING) {
|
||||
System.err.println(result + " = getfield " + getValue(receiver) + "." + elt.getString());
|
||||
} else {
|
||||
walkNodes(elt, context);
|
||||
System.err.println(result + " = reflective getfield " + getValue(receiver) + "." + getValue(elt));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.THROW: {
|
||||
Node catchTarget = context.getCatchFor( null );
|
||||
Node throwVal = n.getFirstChild();
|
||||
walkNodes(throwVal, context);
|
||||
if (catchTarget != null) {
|
||||
System.err.println("THROW of " + getValue(throwVal) + " to " + catchTarget);
|
||||
} else {
|
||||
System.err.println("THROW out of " + getValue(throwVal));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
System.err.println("looking at unhandled " + n + "(" + NT + ")" + " of " + n.getClass());
|
||||
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
|
||||
System.err.println(" with child " + c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ToolErrorReporter reporter = new ToolErrorReporter(true);
|
||||
CompilerEnvirons compilerEnv = new CompilerEnvirons();
|
||||
compilerEnv.setErrorReporter(reporter);
|
||||
|
||||
Parser P = new Parser(compilerEnv, compilerEnv.getErrorReporter());
|
||||
|
||||
final ScriptOrFnNode N = P.parse(new FileReader(args[0]), args[0], 1);
|
||||
walkRhinoTree walker = new walkRhinoTree();
|
||||
|
||||
final Scope G = makeGlobalScope();
|
||||
|
||||
walker.walkNodes( N,
|
||||
new WalkContext() {
|
||||
public ScriptOrFnNode top() { return N; }
|
||||
|
||||
public Scope scope() { return G; }
|
||||
|
||||
public boolean resultWanted() { return true; }
|
||||
|
||||
public Node getCatchFor(Object exceptionType) { return null; }
|
||||
|
||||
public Node getBreakFor(Object label) { return null; }
|
||||
|
||||
public Node getContinueFor(Object label) { return null; }
|
||||
|
||||
public Node getFinally() { return null; }
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue