Example #1
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 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)
Example #3
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)
Example #4
0
 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
Example #5
0
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
Example #6
0
 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
Example #7
0
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
Example #8
0
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
Example #9
0
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 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
Example #11
0
 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)