129 lines
6.1 KiB
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()));
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|
|
}
|
|
}
|