WALA/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/WebPageLoaderFactory.java

129 lines
6.1 KiB
Java

/*******************************************************************************
* Copyright (c) 2013 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.html;
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.js.ssa.JSInstructionFactory;
import com.ibm.wala.cast.js.translator.JSAstTranslator;
import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory;
import com.ibm.wala.cast.tree.visit.CAstVisitor;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.TypeReference;
public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
public WebPageLoaderFactory(JavaScriptTranslatorFactory factory) {
super(factory);
}
public WebPageLoaderFactory(JavaScriptTranslatorFactory factory, CAstRewriterFactory<?, ?> preprocessor) {
super(factory, preprocessor);
}
@Override
protected IClassLoader makeTheLoader(IClassHierarchy cha) {
return new JavaScriptLoader( cha, translatorFactory, preprocessor ) {
@Override
protected TranslatorToIR initTranslator() {
return new JSAstTranslator(this) {
private final CAst Ast = new CAstImpl();
private boolean isNestedWithinScriptBody(WalkContext context) {
return isScriptBody(context) || context.getName().contains("__WINDOW_MAIN__");
}
private boolean isScriptBody(WalkContext context) {
return context.top().getName().equals( "__WINDOW_MAIN__" );
}
@Override
protected int doGlobalRead(CAstNode n, WalkContext context, String name, TypeReference type) {
int result = context.currentScope().allocateTempValue();
if (isNestedWithinScriptBody(context) && ! "$$undefined".equals(name) && !"window".equals(name) && !name.startsWith("$$destructure")) {
// check if field is defined on 'window'
int windowVal = isScriptBody(context)? super.doLocalRead(context, "this", JavaScriptTypes.Root): super.doGlobalRead(n, context, "window", type);
int isDefined = context.currentScope().allocateTempValue();
context.currentScope().getConstantValue(name);
doIsFieldDefined(context, isDefined, windowVal, Ast.makeConstant(name));
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(context.cfg().getCurrentInstruction(),
translateConditionOpcode(CAstOperator.OP_NE),
null,
isDefined,
context.currentScope().getConstantValue(Integer.valueOf(0)),
-1));
PreBasicBlock srcB = context.cfg().getCurrentBlock();
// field lookup of value
context.cfg().newBlock(true);
context.cfg().addInstruction(((JSInstructionFactory) insts).GetInstruction(context.cfg().getCurrentInstruction(), result, windowVal, name));
context.cfg().newBlock(true);
context.cfg().addInstruction(insts.GotoInstruction(context.cfg().getCurrentInstruction(), -1));
PreBasicBlock trueB = context.cfg().getCurrentBlock();
// read global
context.cfg().newBlock(false);
PreBasicBlock falseB = context.cfg().getCurrentBlock();
int sr = super.doGlobalRead(n, context, name, type);
context.cfg().addInstruction(((JSInstructionFactory) insts).AssignInstruction(context.cfg().getCurrentInstruction(), result, sr));
// end
context.cfg().newBlock(true);
context.cfg().addEdge(trueB, context.cfg().getCurrentBlock());
context.cfg().addEdge(srcB, falseB);
return result;
} else {
return super.doGlobalRead(n, context, name, type);
}
}
@Override
protected void doLocalWrite(WalkContext context, String nm, TypeReference type, int rval) {
if (isNestedWithinScriptBody(context) && ! "$$undefined".equals(nm) && !"window".equals(nm) && !nm.startsWith("$$destructure")) {
int windowVal = super.doLocalRead(context, "this", type);
context.currentScope().getConstantValue(nm);
context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(context.cfg().getCurrentInstruction(), windowVal, rval, nm));
}
super.doLocalWrite(context, nm, type, rval);
}
@Override
protected void leaveFunctionStmt(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
super.leaveFunctionStmt(n, context, visitor);
if (isScriptBody(context)) {
CAstEntity fn = (CAstEntity) n.getChild(0).getValue();
int fnValue = context.currentScope().lookup(fn.getName()).valueNumber();
assert fnValue > 0;
int windowVal = super.doLocalRead(context, "this", JavaScriptTypes.Function);
context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(context.cfg().getCurrentInstruction(), windowVal, fnValue, fn.getName()));
}
}
};
}
};
}
}