def visit(self, scopeNode): # go through globals for name,scopeVar in scopeNode.globals().iteritems(): # name might be as little as 'qx' for node in scopeVar.occurrences(): # assemble var var_node = treeutil.findVarRoot(node) var_name = var_node.toJS(None) # e.g. "qx.util.ResourceManager.getInstance" if var_name in lang.QX_CLASS_FACTORIES: # capture qx.*.define() calls succ, class_name, _ = treeutil.isQxDefine(var_node) if succ and class_name: self.new_qx_classes.append(class_name) # lookup in globals_map sKnown_global = self.globals_map.longest_match(var_name) # -> "qx.util.ResourceManager" if sKnown_global: sReplacement = self.globals_map[sKnown_global] # find node in tree dot_number = sKnown_global.count(".") uptimes = u'/'.join(['..'] * dot_number) source_node = treeutil.selectNode(node, uptimes) if uptimes else node # construct replacement repl_node = treegenerator.parse(sReplacement, expr=True) # could be "foo.bar" or "qx.$g['bNq']" # replace known symbol in tree source_node.parent.replaceChild(source_node, repl_node) # update scopeVar.occurrences??!! for child in scopeNode.children: self.visit(child)
def patch(tree, classObj, featureMap): # change this to 'False' if you want logging instead of function removal prune_dont_log = True feature_names = featureMap[classObj.id] # get class map qxDefine = treeutil.findQxDefine(tree) classMap = treeutil.getClassMap(qxDefine) # go through features in 'members' and 'statics' for section in ("statics", "members"): if section in classMap: for feature, node in classMap[section].items(): # skip registered and used keys if feature in feature_names and feature_names[feature].hasref(): continue else: parent = node.parent assert parent.type == "keyvalue" #print "static optimizing: %s#%s" % (classObj.id, feature) if prune_dont_log: # remove sub tree parent.parent.removeChild(parent) # remove the entire feature from the map # remove from featureMap if feature in feature_names: del featureMap[classObj.id][feature] # decrease the ref counts of the contained dependees decrementFromCode(classObj, node, featureMap) else: # OR: only add runtime logging to functions block = treeutil.selectNode(node, 'function/body/block/statements') if block: LogStmt = treegenerator.parse("console.warn('Static optimization would have removed: " + classObj.id + '#' + feature + "');") block.addChild(LogStmt, 0)
def visit(self, scopeNode): # go through globals for name, scopeVar in scopeNode.globals().iteritems(): # name might be as little as 'qx' for node in scopeVar.occurrences(): # assemble var var_node = treeutil.findVarRoot(node) var_name = var_node.toJS( None) # e.g. "qx.util.ResourceManager.getInstance" if var_name in lang.QX_CLASS_FACTORIES: # capture qx.*.define() calls succ, class_name, _ = treeutil.isQxDefine(var_node) if succ and class_name: self.new_qx_classes.append(class_name) # lookup in globals_map sKnown_global = self.globals_map.longest_match( var_name) # -> "qx.util.ResourceManager" if sKnown_global: sReplacement = self.globals_map[sKnown_global] # find node in tree dot_number = sKnown_global.count(".") uptimes = u'/'.join(['..'] * dot_number) source_node = treeutil.selectNode( node, uptimes) if uptimes else node # construct replacement repl_node = treegenerator.parse( sReplacement, expr=True) # could be "foo.bar" or "qx.$g['bNq']" # replace known symbol in tree source_node.parent.replaceChild(source_node, repl_node) # update scopeVar.occurrences??!! for child in scopeNode.children: self.visit(child)
def visit_Literal(self, enode): n = new_symbol("constant", enode) # have to sort out RegExp literals if enode["value"] == {}: # Esprima 1.0.4 represents regexp's as empty map in Json!, so i have # to fall back to the "raw" property. # the online demo esprima.org/demo/parse.html has the regex as a # string in "value" directly!? n = treegenerator.parse(enode["raw"], expr=True) # need esparse --raw here!! else: n = reducer.set_node_type_from_value(n, enode["value"]) return n
def propagate_new_globals(node, new_symbols, globals_map): # make sure there is a wrapping closure node, closure_block = treeutil.ensureClosureWrapper(node) # add new statements at end for new_symbol in new_symbols: # construct statement stmt = "%s = %s;" % (globals_map[new_symbol], new_symbol) # compile to JS stmt_tree = treegenerator.parse(stmt) # attach to node tree closure_block.addChild(stmt_tree) # does append by default
def ensureClosureWrapper(nodes): if not nodes: return None, None # check if we have a closure wrapper already if len(nodes) == 1: closure_statements = is_closure_wrapped(nodes[0]) if closure_statements: return nodes[0], closure_statements # create a closure wrapper and attach argument nodes new_tree = treegenerator.parse("(function(){})();").getChild("call") closure_statements = selectNode(new_tree, wrapper_statements_path) for node in nodes[:]: closure_statements.addChild(node) return new_tree, closure_statements
def propagate_new_globals(node, new_symbols, globals_map): # assuming a container <node>, like <file> or <block> # make sure there is a wrapping closure stmtsNode = node.getChild("statements") new_node, closure_block = treeutil.ensureClosureWrapper(stmtsNode.children) stmtsNode.removeAllChildren() stmtsNode.addChild(new_node) # add new statements at end for new_symbol in new_symbols: # construct statement stmt = "%s = %s;" % (globals_map[new_symbol], new_symbol) # compile to JS stmt_tree = treegenerator.parse(stmt).getFirstChild() # unwrap from 'statments' node # attach to node tree closure_block.addChild(stmt_tree) # does append by default return node
def visit(self, scopeNode): # go through globals for scopeVar in scopeNode.globals(): # this might be as little as 'qx' for node in scopeVar.occurrences(): # assemble var var_node = treeutil.findVarRoot(node) var_name = var_node.toJS() # e.g. "qx.util.ResourceManager.getInstance" # lookup in globals_map known_global, replacement = ( self.global_map.longest_match(var_name)) # -> "qx.util.ResourceManager" # find node in tree dot_number = 0 # TODO uptimes = u'/'.join(['..'] * dot_number) source_node = treeutil.selectNode(node, uptimes) # construct replacement repl_node = treegenerator.parse(replacement) # could be "foo.bar" or "qx.$g['bNq']" # replace known symbol in tree source_node.parent.replaceChild(source_node, repl_node)