Example #1
0
def push(stack, node, parent_idx):
    """
    Push the node's index, and its children's types into stack.
    The stack helps align the frag_info_seq[:] with frag_seq[1:], so that
    each frag in frag_seq knows its parent's id. When predict, we want not
    only the frag itself, but its type (the same as frag's type; so never
    mind) and its parent's type (idx).

    :param stack:
    :param node:
    :param parent_idx:
    :return:
    """
    node_type = get_node_type(node)
    for key in reversed(PROP_DICT[node_type]):
        if key not in node: continue
        child = node[key]

        # If it has a single child
        if (is_single_node(child) and
                get_node_type(child) not in TERM_TYPE):
            frag_type = get_node_type(child)
            frag_info = (parent_idx, frag_type)
            stack.append(frag_info)
        # If it has multiple children
        elif is_node_list(child):
            for _child in reversed(child):
                if (_child is not None and
                        get_node_type(_child) not in TERM_TYPE):
                    frag_type = get_node_type(_child)
                    frag_info = (parent_idx, frag_type)
                    stack.append(frag_info)
Example #2
0
def build_def_dict(node, def_dict):
    node_type = get_node_type(node)

    if node_type in ['ClassExpression', 'FunctionExpression']:
        return

    if (node_type in ['FunctionDeclaration', 'ClassDeclaration']
            and node['id'] != None and node['id']['type'] == 'Identifier'):
        func_name = node['id']['name']
        def_dict.add(func_name)
        return
    elif (node_type == 'VariableDeclarator' and 'type' in node['id']
          and node['id']['type'] == 'Identifier'):
        var_name = node['id']['name']
        def_dict.add(var_name)
    elif (node_type == 'AssignmentExpression' and 'type' in node['left']
          and node['left']['type'] == 'Identifier'):
        var_name = node['left']['name']
        def_dict.add(var_name)

    for key in PROP_DICT[node_type]:
        if key not in node: continue
        child = node[key]

        if (is_single_node(child) and child['type'] not in TERM_TYPE):
            build_def_dict(child, def_dict)
        elif is_node_list(child):
            for _child in child:
                if _child != None:
                    build_def_dict(_child, def_dict)
Example #3
0
    def build_ast(self, node, stack, frag):
        node_type = get_node_type(node)
        for key in PROP_DICT[node_type]:
            if key not in node: continue
            child = node[key]

            # If it has a single child
            if is_single_node(child):
                if not is_pruned(child):
                    frag = self.build_ast(child, stack, frag)
                # Expand the frag
                elif frag:
                    self.push(stack, frag)
                    node[key] = frag
                    return None
            # If it has multiple children
            elif is_node_list(child):
                for idx, _child in enumerate(child):
                    if _child == None:
                        continue
                    elif not is_pruned(_child):
                        frag = self.build_ast(child[idx], stack, frag)
                    # Expand the frag
                    elif frag:
                        self.push(stack, frag)
                        child[idx] = frag
                        return None
        return frag
Example #4
0
    def rewrite(self, node, parser):
        node_type = get_node_type(node)
        if self.is_eval(node):
            # Parse arguments and retrieve new subtrees
            args = node['expression']['arguments']
            org_args = deepcopy(args)
            new_args = self.str2code(args, parser)
            if org_args != new_args:
                return new_args
            else:
                return

        # Recursive traversal
        for key in PROP_DICT[
                node_type]:  # why not iterating over $node's keys? $node can be invalid
            if key not in node: continue  # not every possible prop is in node
            child = node[key]

            if is_single_node(child):
                self.rewrite(child, parser)
            elif is_node_list(child):
                child_idx = 0
                for _child in child:
                    if _child is not None:
                        subtree = self.rewrite(_child, parser)
                        if subtree is not None:
                            node[key] = self.append(node[key], subtree,
                                                    child_idx)
                            child_idx += len(subtree) - 1
                    child_idx += 1
Example #5
0
def normalize_id(node, id_dict, parent=None, prop=None):
    node_type = get_node_type(node)
    if node_type == 'ObjectPattern': return

    for key in PROP_DICT[node_type]:
        if key not in node: continue
        child = node[key]

        # Traversal
        if is_single_node(child):
            normalize_id(child, id_dict, node, key)
        elif is_node_list(child):
            for _child in child:
                if _child is not None:
                    normalize_id(_child, id_dict, node, key)

    # Exit if the node is not an ID
    if node_type != 'Identifier': return

    # Exit if the node is a property of an object
    if (parent['type'] == 'MemberExpression' and prop != 'object'
            and parent['computed'] == False):
        return

    # Do not normalize keys (ObjectExpression)
    if (parent['type'] == 'Property' and prop == 'key'):
        return

    # Replace the ID
    id_name = node['name']
    if id_name in id_dict:
        node['name'] = id_dict[id_name]
Example #6
0
def make_frags(node, frag_seq, frag_info_seq,
               node_types, stack):
    # Append the node before visiting its children
    frag = dict()
    frag_idx = len(frag_seq)  #
    # pre-order depth-first traverse: add root first
    # cannot postpone -- need to increase frag_idx
    frag_seq.append(frag)

    # Push node info into the stack
    if len(stack) > 0:
        frag_info = stack.pop()
        frag_info_seq.append(frag_info)
    push(stack, node, frag_idx)

    node_type = get_node_type(node)
    node_types.add(node_type)

    for key in PROP_DICT[node_type]:
        if key not in node: continue
        child = node[key]

        # If it has a single child
        if (is_single_node(child) and
                get_node_type(child) not in TERM_TYPE):
            frag[key] = prune(child)
            make_frags(child, frag_seq, frag_info_seq,
                       node_types, stack)
        # If it has multiple children
        elif is_node_list(child):
            frag[key] = []
            for _child in child:
                if _child is None:
                    frag[key].append(None)
                elif get_node_type(_child) in TERM_TYPE:
                    frag[key].append(_child)
                else:
                    pruned_child = prune(_child)
                    frag[key].append(pruned_child)
                    make_frags(_child, frag_seq, frag_info_seq,
                               node_types, stack)
        # If it is a terminal (attributes without structure)
        else:
            # print("terminal: ", key, child)
            frag[key] = node[key]

    # Append the fragment -- redundant; can be deleted
    frag_seq[frag_idx] = frag
    return frag
Example #7
0
def make_edges(node, frag_seq, frag_info_seq,
               node_types, stack):
    node_type = get_node_type(node)

    for key in PROP_DICT[node_type]:
        if key not in node: continue

        node_types.add(node_type)
        # Append the node before visiting its children
        frag = dict()
        frag_idx = len(frag_seq)
        frag_seq.append(frag)

        # Push node info into the stack
        if len(stack) > 0:
            frag_info = stack.pop()
            frag_info_seq.append(frag_info)
        push(stack, node, frag_idx)

        child = node[key]

        # If it has a single child
        if (is_single_node(child) and
                get_node_type(child) not in TERM_TYPE):
            frag[(node_type, key)] = prune(child)
            make_edges(child, frag_seq, frag_info_seq,
                       node_types, stack)
        # If it has multiple children
        elif is_node_list(child):
            frag[(node_type, key)] = []
            for _child in child:
                if _child is None:
                    frag[(node_type, key)].append(None)
                elif get_node_type(_child) in TERM_TYPE:
                    frag[(node_type, key)].append(_child)
                else:
                    pruned_child = prune(_child)
                    frag[(node_type, key)].append(pruned_child)
                    make_edges(_child, frag_seq, frag_info_seq,
                               node_types, stack)
        # If it is a terminal
        else:
            frag[(node_type, key)] = node[key]

        # Append the fragment
        frag_seq[frag_idx] = frag
Example #8
0
def push(stack, node, parent_idx):
    node_type = get_node_type(node)
    for key in reversed(PROP_DICT[node_type]):
        if key not in node: continue
        child = node[key]

        # If it has a single child
        if (is_single_node(child) and get_node_type(child) not in TERM_TYPE):
            frag_type = get_node_type(child)
            frag_info = (parent_idx, frag_type)
            stack.append(frag_info)
        # If it has multiple children
        elif is_node_list(child):
            for _child in reversed(child):
                if (_child is not None
                        and get_node_type(_child) not in TERM_TYPE):
                    frag_type = get_node_type(_child)
                    frag_info = (parent_idx, frag_type)
                    stack.append(frag_info)
Example #9
0
def func_hoisting(node, sym_list):
  if node == None: return
  node_type = get_node_type(node)
  for key in PROP_DICT[node_type]:
    if key not in node: continue
    child = node[key]

    if is_single_node(child):
      if get_node_type(child) == 'FunctionDeclaration':
        sym_list.append(Symbol(child['id'], child, JSType.js_func))
      elif get_node_type(child) == 'BlockStatement':
        func_hoisting(child, sym_list)
    elif is_node_list(child):
      for _child in child:
        if _child == None: continue
        if get_node_type(_child) == 'FunctionDeclaration':
          sym_list.append(Symbol(_child['id'], _child, JSType.js_func))
        elif get_node_type(_child) == 'BlockStatement':
          func_hoisting(_child, sym_list)
Example #10
0
    def traverse(self, node, frag_seq, stack):
        node_type = get_node_type(node)
        if node_type not in TERM_TYPE:
            parent_idx = self.frag2idx(node)
        else:
            return

        for key in PROP_DICT[node_type]:
            if key not in node: continue
            child = node[key]

            # If it has a single child
            if is_single_node(child):
                if is_pruned(child):
                    frag_idx = frag_seq.pop(0)
                    if frag_idx == -1:
                        if stack != None:
                            frag_info = (parent_idx,
                                         get_node_type(child))
                            stack.append(frag_info)
                        continue
                    frag = self.idx2frag(frag_idx)
                    node[key] = frag
                self.traverse(node[key], frag_seq, stack)
            # If it has multiple children
            elif is_node_list(child):
                for idx, _child in enumerate(child):
                    if _child == None:
                        continue
                    elif is_pruned(_child):
                        frag_idx = frag_seq.pop(0)
                        if frag_idx == -1:
                            if stack != None:
                                frag_info = (parent_idx,
                                             get_node_type(_child))
                                stack.append(frag_info)
                            continue
                        frag = self.idx2frag(frag_idx)
                        child[idx] = frag
                    self.traverse(child[idx], frag_seq, stack)
Example #11
0
def var_hoisting(node, parent, sym_list):
    node_type = get_node_type(node)
    if node_type in [
            'FunctionDeclaration', 'FunctionExpression', 'ClassDeclaration',
            'ClassExpression'
    ]:
        return
    elif (parent != None and get_node_type(parent) == 'VariableDeclaration'
          and parent['kind'] == 'var' and node_type == 'VariableDeclarator'):
        symbols = pattern_hoisting(node['id'], node)
        sym_list += symbols
    else:
        for key in PROP_DICT[node_type]:
            if key not in node: continue
            child = node[key]

            if (is_single_node(child)
                    and get_node_type(child) not in TERM_TYPE):
                var_hoisting(child, node, sym_list)
            elif is_node_list(child):
                for _child in child:
                    if _child != None:
                        var_hoisting(_child, node, sym_list)
Example #12
0
def collect_id(node, id_dict, id_cnt, parent=None, prop=None):
    node_type = get_node_type(node)

    # Tree traversal
    for key in PROP_DICT[node_type]:
        if key not in node: continue
        child = node[key]

        if is_single_node(child):
            collect_id(child, id_dict, id_cnt, node, key)
        elif is_node_list(child):
            for _child in child:
                if _child is not None:
                    collect_id(_child, id_dict, id_cnt, node, key)

    if parent is not None and is_func_decl(parent):
        id_type = 'f'
    else:
        id_type = 'v'

    if is_declared_id(node, parent, prop):
        id_name = node['name']
        add_id(id_name, id_dict, id_cnt, id_type)
Example #13
0
def resolve_id(node,
               parent,
               symbols,
               is_global,
               is_check=False,
               cand=[],
               hlist=[]):
    if node == None: return symbols

    node_type = get_node_type(node)
    if node_type == 'Identifier':
        return resolve_identifier(node, parent, symbols, is_global, is_check,
                                  cand, hlist)
    elif (node_type == 'MemberExpression' and node['computed'] == False):
        return resolve_id(node['object'], node, symbols, is_global, is_check,
                          cand, hlist)
    elif node_type == 'CallExpression':
        return resolve_FuncCall(node, parent, symbols, is_global, is_check,
                                cand, hlist)
    elif node_type == 'AssignmentExpression':
        return resolve_Assign(node, parent, symbols, is_global, is_check, cand,
                              hlist)
    elif node_type == 'VariableDeclarator':
        return resolve_VarDecl(node, parent, symbols, is_global, is_check,
                               cand, hlist)
    elif node_type in ['FunctionDeclaration', 'FunctionExpression']:
        return symbols
    elif node_type == 'IfStatement':
        return resolve_If(node, parent, symbols, is_global, is_check, cand,
                          hlist)
    elif node_type in ['DoWhileStatement', 'WhileStatement']:
        return resolve_While(node, parent, symbols, is_global, is_check, cand,
                             hlist)
    elif node_type == 'ForStatement':
        return resolve_For(node, parent, symbols, is_global, is_check, cand,
                           hlist)
    elif node_type in ['ForInStatement', 'ForOfStatement']:
        return resolve_ForIn(node, parent, symbols, is_global, is_check, cand,
                             hlist)
    elif node_type == 'WithStatment':
        return resolve_With(node, parent, symbols, is_global, is_check, cand,
                            hlist)
    elif node_type == 'TryStatement':
        return resolve_Try(node, parent, symbols, is_global, is_check, cand,
                           hlist)
    elif node_type == 'Property':
        return resolve_id(node['value'], node, symbols, is_global, is_check,
                          cand, hlist)
    elif node_type in ['ClassDeclaration', 'ClassExpression']:
        return resolve_ClassDecl(node, parent, symbols, is_global, is_check,
                                 cand, hlist)

    # Switch
    for key in PROP_DICT[node_type]:
        if key not in node: continue
        child = node[key]

        if (is_single_node(child) and get_node_type(child) not in TERM_TYPE):
            resolve_id(child, node, symbols, is_global, is_check, cand, hlist)
        elif is_node_list(child):
            resolve_list(child, node, symbols, is_global, is_check, cand,
                         hlist)
    return symbols