Skip to content

Commit

Permalink
cumulative updates
Browse files Browse the repository at this point in the history
  • Loading branch information
amoeller committed Nov 28, 2016
1 parent 6ea656b commit fd29f73
Show file tree
Hide file tree
Showing 31 changed files with 11,987 additions and 186 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
.idea/workspace.xml
**/*.iml
/local-development.properties
!/test/expected/**
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,5 @@ This software includes components from:
- Google Closure Compiler (<http://code.google.com/p/closure-compiler/>)
- Jericho HTML Parser (<http://jericho.htmlparser.net/>)
- Log4j (<http://logging.apache.org/log4>)


- args4j (<http://args4j.kohsuke.org/>)
- JUnit (<http://junit.org/>) (development only)
2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<property name="project" value="tajs" />
<property name="version" value="0.9" />
<property name="release" value="9" />
<property name="release" value="10" />

<property name="optimize" value="on" />
<property name="debug" value="off" />
Expand Down
14 changes: 1 addition & 13 deletions local-development.example.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,4 @@ dot = /usr/bin/dot
# dot = C:/Program Files/ATT/Graphviz/bin/dot.exe

imgviewer = /usr/bin/gthumb
# imgviewer = C:/Program Files/Google/Picasa3/PicasaPhotoViewer.exe

nodejs = /home/esbena/.nvm/versions/node/v0.12.7/bin/node

jsdelta_dir = /home/esbena/tmp/jsdelta

classpath = \
/home/esbena/workspace/TAJS-complete/out/production/TAJS:\
/home/esbena/workspace/TAJS-complete/out/test/TAJS:\
/home/esbena/workspace/TAJS-complete/out/production/TAJS-meta:\
/home/esbena/workspace/TAJS-complete/out/test/TAJS-meta:\
/home/esbena/_data/TAJS/lib/*:\
/home/esbena/_data/TAJS-meta/lib/*
# imgviewer = C:/Program Files/Google/Picasa3/PicasaPhotoViewer.exe
Binary file modified misc/package-dependencies.dia
Binary file not shown.
Binary file modified misc/package-dependencies.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions src/dk/brics/tajs/analysis/FunctionCalls.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects;
import dk.brics.tajs.flowgraph.AbstractNode;
import dk.brics.tajs.flowgraph.jsnodes.CallNode;
import dk.brics.tajs.flowgraph.jsnodes.Node;
import dk.brics.tajs.lattice.ExecutionContext;
import dk.brics.tajs.lattice.ObjectLabel;
import dk.brics.tajs.lattice.ObjectLabel.Kind;
Expand Down Expand Up @@ -199,7 +198,7 @@ public ExecutionContext getExecutionContext() {
*/
public static class EventHandlerCall implements CallInfo {

private Node sourceNode;
private AbstractNode sourceNode;

private Value function;

Expand All @@ -211,7 +210,7 @@ public static class EventHandlerCall implements CallInfo {
*/
private final Set<ObjectLabel> thisTargets;

public EventHandlerCall(Node sourceNode, Value function, List<Value> args, Set<ObjectLabel> thisTargets, State state) {
public EventHandlerCall(AbstractNode sourceNode, Value function, List<Value> args, Set<ObjectLabel> thisTargets, State state) {
this.sourceNode = sourceNode;
this.function = function;
this.args = args;
Expand All @@ -225,7 +224,7 @@ public AbstractNode getSourceNode() {
}

@Override
public Node getJSSourceNode() {
public AbstractNode getJSSourceNode() {
return sourceNode;
}

Expand Down
3 changes: 3 additions & 0 deletions src/dk/brics/tajs/analysis/InitialStateBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ public void addInitialState(BasicBlock global_entry_block, Solver.SolverInterfac
createPrimitiveFunction(lStringProto, lFunProto, ECMAScriptObjects.STRING_TOUPPERCASE, "toUpperCase", 0, c);
createPrimitiveFunction(lStringProto, lFunProto, ECMAScriptObjects.STRING_TOLOCALEUPPERCASE, "toLocaleUpperCase", 0, c);
createPrimitiveFunction(lStringProto, lFunProto, ECMAScriptObjects.STRING_TRIM, "trim", 0, c);
createPrimitiveFunction(lStringProto, lFunProto, ECMAScriptObjects.STRING_STARTSWITH, "startsWith", 2, c);
createPrimitiveFunction(lStringProto, lFunProto, ECMAScriptObjects.STRING_ENDSWITH, "endsWith", 2, c);


// 15.6.4 properties of the Boolean prototype object
Expand All @@ -394,6 +396,7 @@ public void addInitialState(BasicBlock global_entry_block, Solver.SolverInterfac
createPrimitiveFunction(lNumberProto, lFunProto, ECMAScriptObjects.NUMBER_TOFIXED, "toFixed", 1, c);
createPrimitiveFunction(lNumberProto, lFunProto, ECMAScriptObjects.NUMBER_TOEXPONENTIAL, "toExponential", 1, c);
createPrimitiveFunction(lNumberProto, lFunProto, ECMAScriptObjects.NUMBER_TOPRECISION, "toPrecision", 1, c);
createPrimitiveFunction(lNumber, lFunProto, ECMAScriptObjects.NUMBER_ISFINITE, "isFinite", 1, c);

// 15.8 the Math object
pv.writePropertyWithAttributes(global, "Math", Value.makeObject(lMath).setAttributes(true, false, false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.JSON_PARSE;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.JSON_STRINGIFY;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.NUMBER;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.NUMBER_ISFINITE;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.NUMBER_TOEXPONENTIAL;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.NUMBER_TOFIXED;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.NUMBER_TOLOCALESTRING;
Expand All @@ -65,6 +66,7 @@
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_CHARAT;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_CHARCODEAT;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_CONCAT;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_ENDSWITH;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_FROMCHARCODE;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_INDEXOF;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_LASTINDEXOF;
Expand All @@ -74,6 +76,7 @@
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_SEARCH;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_SLICE;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_SPLIT;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_STARTSWITH;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_SUBSTR;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_SUBSTRING;
import static dk.brics.tajs.analysis.nativeobjects.ECMAScriptObjects.STRING_TOLOCALELOWERCASE;
Expand Down Expand Up @@ -246,8 +249,11 @@ public boolean maybeNotSatisfied(Value v) {
addSig(signatures, STRING_TOUPPERCASE, rCoerceString);
addSig(signatures, STRING_TOLOCALEUPPERCASE, rCoerceString);
addSig(signatures, STRING_TRIM, rCoerceString);
addSig(signatures, STRING_STARTSWITH, rCoerceString, mpStringIfNotRegExp, pInteger);
addSig(signatures, STRING_ENDSWITH, rCoerceString, mpStringIfNotRegExp, pInteger);

// NUMBER FUNCTIONS
addStaticSig(signatures, NUMBER_ISFINITE, false, mpDontCare);
addSig(signatures, NUMBER_TOFIXED, rNumber, pInteger);
addSig(signatures, NUMBER_TOEXPONENTIAL, rNumber, pInteger);
addSig(signatures, NUMBER_TOPRECISION, rNumber, pInteger);
Expand Down Expand Up @@ -609,6 +615,9 @@ public VarSignature(boolean isConstructor, ValueDescription base, List<Parameter
this.fixedParameterCount = fixedParameters.size();
this.simpleSignature = new SimpleSignature(isConstructor, base, fixedParameters);
this.varParameter = parameters.get(parameters.size() - 1);
if (this.varParameter.mustBePresent) {
throw new AnalysisException("The last VarSig parameter should not be mandatory.");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,11 @@ public HeapContext makeFunctionHeapContext(Function function, Solver.SolverInter
}

public HeapContext makeHeapContext(AbstractNode location, ContextArguments arguments) {
boolean recursive = ContextArguments.extractTopLevelObjectLabels(arguments).stream().anyMatch(location::equals); // FIXME: types don't match, wrong 'equals'?
boolean recursive = ContextArguments.extractTopLevelObjectLabels(arguments).stream().anyMatch(l -> {
SourceLocation thisAllocationSite = location.getSourceLocation();
SourceLocation otherAllocationSite = l.getSourceLocation();
return thisAllocationSite.equals(otherAllocationSite);
});
if (recursive) {
// System.out.printf("Avoiding creation of recursive objectlabel at %s: %s%n", location, arguments);
return HeapContext.make(null, null);
Expand Down
22 changes: 15 additions & 7 deletions src/dk/brics/tajs/analysis/dom/DOMBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import net.htmlparser.jericho.Source;

import java.util.Arrays;
import java.util.Collection;
import java.util.Set;

import static dk.brics.tajs.analysis.dom.DOMFunctions.createDOMProperty;
Expand Down Expand Up @@ -179,8 +180,9 @@ public static void addInitialState(Source document, Solver.SolverInterface c) {
createDOMProperty(instance, "channelCountMode", Value.makeAnyStr(), c);
createDOMProperty(instance, "channelInterpretation", Value.makeAnyStr(), c);
}
writeNullOnEventProperties(singleton(HTMLElement.ELEMENT_PROTOTYPE), c.getAnalysis().getPropVarOperations());
writeNullOnEventProperties(singleton(DOMWindow.WINDOW), c.getAnalysis().getPropVarOperations());

Collection<ObjectLabel> evenNameContainers = Arrays.asList(HTMLElement.ELEMENT_PROTOTYPE, HTMLElement.ELEMENT_ATTRIBUTES, DOMWindow.WINDOW);
writeEventListenerProperties(evenNameContainers, c.getAnalysis().getPropVarOperations());

DOMFunctions.makeAnyHTMLNodeList(c);
if (document != null) {
Expand Down Expand Up @@ -242,10 +244,16 @@ public static Set<ObjectLabel> getAllHtmlObjectLabels() {
return ALL_HTML_OBJECT_LABELS;
}

public static void writeNullOnEventProperties(Set<ObjectLabel> targets, PropVarOperations pv){
EventType.getAllEventTypeNames().stream().forEach(name -> {
String onName = "on" + name;
pv.writeProperty(targets, Value.makeTemporaryStr(onName), Value.makeNull().setAttributes(false, false, false), false, true);
});
public static void writeEventListenerProperties(Collection<ObjectLabel> targets, PropVarOperations pv) {
Arrays.asList(EventType.values()).stream().forEach(type ->
EventType.getEventHandlerAttributeNames(type).forEach(attributeName ->
targets.forEach(target -> {
Value event = DOMEvents.getEvent(type);
boolean maybePresent = type == EventType.OTHER; // support for some of these event types is spotty
pv.writeProperty(singleton(target), Value.makeTemporaryStr(attributeName), Value.makeNull().join(event).setAttributes(false, false, false), maybePresent, true);
}
)
)
);
}
}
97 changes: 72 additions & 25 deletions src/dk/brics/tajs/analysis/dom/DOMEvents.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import dk.brics.tajs.analysis.InitialStateBuilder;
import dk.brics.tajs.analysis.PropVarOperations;
import dk.brics.tajs.analysis.Solver;
import dk.brics.tajs.flowgraph.AbstractNode;
import dk.brics.tajs.flowgraph.EventType;
import dk.brics.tajs.flowgraph.jsnodes.EventDispatcherNode;
import dk.brics.tajs.lattice.ObjectLabel;
Expand Down Expand Up @@ -53,9 +54,15 @@ public class DOMEvents {

private static final Value anyEvent;

private static final Value timeoutEvent;

private static final Value unloadEvent;

static {
anyEvent = createAnyEvent();
loadEvent = createAnyLoadEvent();
timeoutEvent = Value.makeNone();
unloadEvent = Value.makeNone();
if (Options.get().isSingleEventHandlerType()) {
keyboardEvent = anyEvent;
} else {
Expand Down Expand Up @@ -150,73 +157,113 @@ private static DOMRegistry.MaySets mapEventTypeToMaySetKey(EventType kind) {
*/
private static Set<ObjectLabel> toEventHandler(Value value, Solver.SolverInterface c) {
value = UnknownValueResolver.getRealValue(value, c.getState());

Set<ObjectLabel> handlers = Collections.newSet();

boolean maybeNonFunction = value.isMaybePrimitive();

for (ObjectLabel objectLabel : value.getObjectLabels()) {
if (objectLabel.getKind() == ObjectLabel.Kind.FUNCTION) {
handlers.add(objectLabel);
} else {
maybeNonFunction = true;
}
}

if (maybeNonFunction) {
c.getMonitoring().addMessage(c.getNode(), Message.Severity.HIGH, "TypeError, non-function event handler");
}

return handlers;
}

private static void triggerEventHandler(EventDispatcherNode currentNode, State currentState, DOMRegistry.MaySets eventhandlerKind, Value event, boolean requiresStateCloning, Solver.SolverInterface c) {
Set<ObjectLabel> handlers = currentState.getExtras().getFromMaySet(eventhandlerKind.name());
private static void triggerEventHandler(AbstractNode currentNode, State currentState, EventType type, boolean requiresStateCloning, Solver.SolverInterface c, Set<ObjectLabel> handlers) {
Value event = getEvent(type);
if (handlers.isEmpty()) {
return;
}
State callState = requiresStateCloning ? currentState.clone() : currentState;
c.withState(callState, () -> {
for (ObjectLabel l : handlers) {
log.debug("Triggering eventHandlers <" + eventhandlerKind + ">: " + l);
log.debug("Triggering eventHandlers <" + type.toString() + ">: " + l);
}

if (event != null) {
if (!event.isNone()) {
// Support the unofficial window.event property that is set by the browser
PropVarOperations pv = c.getAnalysis().getPropVarOperations();
pv.writeProperty(DOMWindow.WINDOW, "event", event); // strong write to override old value
pv.deleteProperty(singleton(DOMWindow.WINDOW), Value.makeTemporaryStr("event"), true); // weak delete to emulate unofficial
}

Set<ObjectLabel> thisTargets;
if (eventhandlerKind == DOMRegistry.MaySets.TIMEOUT_EVENT_HANDLERS) {
if (type == EventType.TIMEOUT) {
thisTargets = singleton(InitialStateBuilder.GLOBAL);
} else {
thisTargets = DOMBuilder.getAllDOMEventTargets();
}
List<Value> args = event == null ? newList() : Collections.singletonList(event);
List<Value> args = event.isNone() ? newList() : Collections.singletonList(event);
FunctionCalls.callFunction(new FunctionCalls.EventHandlerCall(currentNode, Value.makeObject(handlers), args, thisTargets, callState), c);
});
}

public static Value getEvent(EventType type) {
switch (type) {
case LOAD:
return loadEvent;
case UNLOAD:
return unloadEvent;
case KEYBOARD:
return keyboardEvent;
case MOUSE:
return mouseEvent;
case AJAX:
return ajaxEvent;
case TIMEOUT:
return timeoutEvent;
case OTHER:
case UNKNOWN:
return anyEvent;
default:
throw new AnalysisException("Unhandleded case: " + type);
}
}

private static void triggerEventHandler(EventType type, Solver.SolverInterface c) {
boolean requiresStateCloning = type == EventType.LOAD || type == EventType.UNLOAD;
DOMRegistry.MaySets maysetKey = convertEventTypeToHandlerKey(type);
triggerEventHandler(c.getNode(), c.getState(), type, requiresStateCloning, c, c.getState().getExtras().getFromMaySet(maysetKey.name()));
}

private static DOMRegistry.MaySets convertEventTypeToHandlerKey(EventType type) {
switch (type) {
case LOAD:
return DOMRegistry.MaySets.LOAD_EVENT_HANDLER;
case UNLOAD:
return DOMRegistry.MaySets.UNLOAD_EVENT_HANDLERS;
case KEYBOARD:
return DOMRegistry.MaySets.KEYBOARD_EVENT_HANDLER;
case MOUSE:
return DOMRegistry.MaySets.MOUSE_EVENT_HANDLER;
case UNKNOWN:
return DOMRegistry.MaySets.UNKNOWN_EVENT_HANDLERS;
case OTHER:
return DOMRegistry.MaySets.UNKNOWN_EVENT_HANDLERS; // TODO improve precision
case AJAX:
return DOMRegistry.MaySets.AJAX_EVENT_HANDLER;
case TIMEOUT:
return DOMRegistry.MaySets.TIMEOUT_EVENT_HANDLERS;
default:
throw new AnalysisException("Unhandled case: " + type);
}
}

public static void emit(EventDispatcherNode n, Solver.SolverInterface c) {
State state = c.getState();
if (n.getType() == EventDispatcherNode.Type.DOM_LOAD) {
triggerEventHandler(n, state, DOMRegistry.MaySets.LOAD_EVENT_HANDLER, loadEvent, false, c);
triggerEventHandler(EventType.LOAD, c);
}

if (n.getType() == EventDispatcherNode.Type.DOM_UNLOAD) {
triggerEventHandler(n, state, DOMRegistry.MaySets.UNLOAD_EVENT_HANDLERS, null, false, c);
triggerEventHandler(EventType.UNLOAD, c);
}

if (n.getType() == EventDispatcherNode.Type.DOM_OTHER) {
triggerEventHandler(n, state, DOMRegistry.MaySets.KEYBOARD_EVENT_HANDLER, keyboardEvent, true, c);
triggerEventHandler(n, state, DOMRegistry.MaySets.MOUSE_EVENT_HANDLER, mouseEvent, true, c);
triggerEventHandler(n, state, DOMRegistry.MaySets.AJAX_EVENT_HANDLER, ajaxEvent, true, c);
// not adding precise support for touch events, they are represented in the anyEvent
triggerEventHandler(n, state, DOMRegistry.MaySets.UNKNOWN_EVENT_HANDLERS, anyEvent, true, c);
triggerEventHandler(n, state, DOMRegistry.MaySets.TIMEOUT_EVENT_HANDLERS, null, true, c);
triggerEventHandler(EventType.KEYBOARD, c);
triggerEventHandler(EventType.MOUSE, c);
triggerEventHandler(EventType.AJAX, c);
triggerEventHandler(EventType.UNKNOWN, c);
triggerEventHandler(EventType.OTHER, c);
triggerEventHandler(EventType.TIMEOUT, c);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public static Value evaluate(ECMAScriptObjects nativeobject, CallInfo call, Solv
case NUMBER_TOLOCALESTRING:
case NUMBER_TOSTRING:
case NUMBER_VALUEOF:
case NUMBER_ISFINITE:
res = JSNumber.evaluate(nativeobject, call, c);
break;

Expand Down Expand Up @@ -203,6 +204,8 @@ public static Value evaluate(ECMAScriptObjects nativeobject, CallInfo call, Solv
case STRING_CHARCODEAT:
case STRING_CHARAT:
case STRING_TRIM:
case STRING_ENDSWITH:
case STRING_STARTSWITH:
res = JSString.evaluate(nativeobject, call, c);
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public enum ECMAScriptObjects implements HostObject {
STRING_TOUPPERCASE("String.prototype.toUpperCase"),
STRING_TOLOCALEUPPERCASE("String.prototype.toLocaleUpperCase"),
STRING_TRIM("String.prototype.trim"),
STRING_STARTSWITH("String.prototype.startsWith"),
STRING_ENDSWITH("String.prototype.endsWith"),

BOOLEAN("Boolean"),
BOOLEAN_PROTOTYPE("Boolean.prototype"),
Expand All @@ -98,6 +100,7 @@ public enum ECMAScriptObjects implements HostObject {
NUMBER_TOFIXED("Number.prototype.toFixed"),
NUMBER_TOEXPONENTIAL("Number.prototype.toExponential"),
NUMBER_TOPRECISION("Number.prototype.toPrecision"),
NUMBER_ISFINITE("Number.isFinite"),

MATH("Math"),
MATH_MAX("Math.max"),
Expand Down
Loading

0 comments on commit fd29f73

Please sign in to comment.