# -*- coding: utf-8 -*- # # ********************************************************************************************************************* # TinyJSParser https://github.com/TmpName/TinyJSParser # # A basic JS interpreter in python, made for the Kodi addon Vstream https://github.com/Kodi-vStream/venom-xbmc-addons # # ********************************************************************************************************************* # TODO LIST # --------- # Regex will work only for normal name, not for exotic name # Object # Globla/Local variables/function/object # utiliser un tableau special pr variable passe en parametres > clash # help # https://sarfraznawaz.wordpress.com/2012/01/26/javascript-self-invoking-functions/ # https://nemisj.com/python-api-javascript/ # https://fr.wikiversity.org/wiki/Python/Les_types_de_base # https://javascriptobfuscator.com/Javascript-Obfuscator.aspx # https://nemisj.com/python-api-javascript/ # UNICODE ERROR # print(a.decode('utf-8').encode('ascii', 'replace')) # true = 1 instead of true # phrase=raw_input() # phrase.xxx # https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/ import re import types from types import NoneType import math # import time # import sys REG_NAME = '[\w]+' REG_OP = '[\/\*\-\+<>\|\&=~^%!]+' # not space here, and no bracket DEBUG = False # Never enable it in kodi, too big size log MAX_RECURSION = 50 ALPHA = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' # if(!_0x45ae41[_0x5949('28')](_0x5949('9'),document)||!(!(typeof (document.write) == 'undefined'))){ # --------------------------------------------------------------------------------- def logwrite(stri): fh = open('G:\\JSparser\\debug.txt', 'a') fh.write(stri + '\n') fh.close() def RemoveGuil(string): if not (isinstance(string, types.StringTypes)): return string string = string.strip() if string.startswith('"') and string.endswith('"'): return string[1:-1] if string.startswith("'") and string.endswith("'"): return string[1:-1] return string def ASCIIDecode(string): i = 0 l = len(string) ret = '' while i < l: c = string[i] if string[i:(i + 2)] == '\\x': c = chr(int(string[(i + 2):(i + 4)], 16)) i += 3 if string[i:(i+2)] == '\\u': c = chr(int(string[(i + 2):(i + 6)], 16)) i += 5 ret = ret + c i += 1 return ret def IsUnicode(s): if isinstance(s, unicode): return True return False def out(string): if DEBUG: print(str(string.decode('latin-1').encode('ascii', 'replace'))) def Ustr(string): if isinstance(string, unicode): return str(string.encode('ascii', 'replace')) return str(string) def GetNextchar(string, pos): if len(string) <= (pos + 1): return '' return string[pos + 1] def GetNextUsefullchar(string): j = 0 try: while string[j].isspace(): j += 1 except: return '', 0 return string[j], j def GetPrevchar(string, pos): if (pos - 1) < 0: return '' return string[pos - 1] def CheckType(value): if isinstance(value, types.StringTypes): return 'String' if isinstance(value, bool): return 'Bool' if isinstance(value, (int, long, float)): return 'Numeric' if type(value) in [list, tuple, dict]: return 'Array' if isinstance(value, NoneType): return 'Undefined' if isinstance(value, fonction): return 'Fonction' return 'Unknow' # Fonction to return only one parameter from a string with correct closed [] () "" and '' def GetItemAlone(string, separator=' '): l = len(string) - 1 ret = '' i = -1 p = 0 # parenthese a = 0 # accolade b = 0 # bracket c1 = 0 # chain with " c2 = 0 # chain with ' n = False last_char = '' s = False while i < l: i += 1 ch = string[i] ret = ret + ch n = False # Return if the is complete and before the char wanted but not if it's the first one if (ch in separator) and not p and not a and not b and not c1 and not c2 and not n and (i > 0): return ret[:-1] # Skip empty space if ch.isspace(): continue if ch == '"' and not GetPrevchar(string, i) == '\\' and not c2: c1 = 1 - c1 if ch == "'" and not GetPrevchar(string, i) == '\\' and not c1: c2 = 1 - c2 if not c1 and not c2: if ch == '(': p += 1 if ch == ')': p -= 1 if ch == '{': a += 1 if ch == '}': a -= 1 if ch == '[': b += 1 if ch == ']': b -= 1 if ch == '.' and not ((last_char in '0123456789') or (string[i + 1] in '0123456789')): n = True # return if the chain is complete but with the char wanted if (ch in separator) and not p and not a and not b and not c1 and not c2 and not n and (i > 0): return ret last_char = ch return ret def MySplit(string, char, NoEmpty=False): r = [] l = len(string) i = 0 chain = 0 p = 0 e = '' if not l: if NoEmpty: return [] while l > i: c = string[i] if c == '"': chain = 1-chain if c == '(': p += 1 if c == ')': p -= 1 if (c == char) and not chain and not p: r.append(e.strip()) e = '' else: e += c i += 1 r.append(e.strip()) return r def GetConstructor(value): if isinstance(value, (int, long)): r = fonction('Number', '', '\n [native code]\n', True) return r elif isinstance(value, fonction): r = fonction('Function', '', '\n [native code]\n', True) return r elif isinstance(value, types.StringTypes): r = fonction('String', '', '\n [native code]\n', True) return r return '' class JSBuffer(object): PRIORITY = {'+': 3, '-': 3, '*': 4, '/': 4, '>': 1, '<': 1, '&': 2, '|': 2} def __init__(self): self.type = None self.buffer = '' self.__op = '' self.__value = None # buffers self.buf = [] self.opBuf = [] def SetOp(self, op): if (op == '&') and (self.__op == '&'): return if (op == '|') and (self.__op == '|'): return else: self.__op = self.__op + op def CheckString(self): if len(self.buf) >= len(self.opBuf): return True return False # Need 3 values for priority def AddValue(self, value): out('ADD ' + Ustr(value) + ' ' + Ustr(type(value)) + ' a ' + Ustr(self.buf)) if not self.type: self.type = CheckType(value) self.Push(value, self.__op) return if not self.__op: out('op ' + str(self.opBuf) + ' - buff ' + str(self.buf)) raise Exception('Missing operator') self.Push(value, self.__op) self.__op = '' def GetPrevious(self): ret = None if len(self.buf) > 0: ret = self.buf[-1] del self.buf[-1] self.__op = self.opBuf[-1] del self.opBuf[-1] if not len(self.buf): self.type = None return ret def Compute(self): # check type if len(self.buf) > 1: if not (self.type == CheckType(self.buf[len(self.buf) - 1])): # Type different mais juste operation logique if self.opBuf[1] == '==': self.type = 'Logic' # Type different mais JS convertis en string else: out('string convertion') if not CheckType(self.buf[0]) == 'String': self.buf[0] = self.SpecialStr(self.buf[0]) if len(self.buf) > 1: if not CheckType(self.buf[1]) == 'String': self.buf[1] = self.SpecialStr(self.buf[1]) self.type = 'String' # Work for operateur + | ! if self.type == 'String': if '!' in self.opBuf[0]: self.buf[0] = not self.buf[0] self.opBuf[0] = self.opBuf[0].replace('!', '') if len(self.buf) > 1: if self.opBuf[1] == '!': self.buf[1] = not self.buf[1] self.opBuf[1] = self.opBuf[1].replace('!', '') if self.opBuf[1] == '+': self.buf[0] = self.buf[0] + self.buf[1] if self.opBuf[1] == '|': if not self.buf[0]: self.buf[0] = self.buf[1] if '==' in self.opBuf[1]: self.buf[0] = (self.buf[1] == self.buf[0]) self.type == 'Logic' if '!=' in self.opBuf[1]: self.buf[0] = (self.buf[1] != self.buf[0]) self.type == 'Logic' # decale del self.opBuf[-1] del self.buf[-1] # work for all operator elif self.type == 'Numeric': if len(self.buf) > 1: self.buf[0] = self.opBuf[0] + str(self.buf[0]) + self.opBuf[1] + str(self.buf[1]) self.opBuf[0] = '' # decale del self.opBuf[-1] del self.buf[-1] else: self.buf[0] = self.opBuf[0] + str(self.buf[0]) self.opBuf[0] = '' # work for bool elif self.type == 'Bool': if len(self.buf) > 1: self.buf[0] = self.opBuf[0] + str(self.buf[0]) + self.opBuf[1] + str(self.buf[1]) self.opBuf[0] = '' # decale del self.opBuf[-1] del self.buf[-1] else: self.buf[0] = self.opBuf[0] + str(self.buf[0]) self.opBuf[0] = '' # work for elif self.type == 'Logic': if not self.buf[0] == self.buf[1]: self.buf[0] = False else: self.buf[0] = True # decale del self.opBuf[-1] del self.buf[-1] elif len(self.buf) > 1: print(self.type) print(self.buf) print(self.opBuf) raise Exception("Can't compute") # on decale tout def Push(self, value, op): if len(self.buf) > 1: self.Compute() self.buf.append(value) self.opBuf.append(op) return def SpecialStr(self, value): if CheckType(value) == 'Numeric': return str(value) if value == None: return 'Undefined' if value == True: return 'true' if value == False: return 'false' if type(value) in [list]: convert_first_to_generator = (str(w) for w in value) return ','.join(convert_first_to_generator) if type(value) in [dict]: return '[object Object]' if CheckType(value) == 'Fonction': return value.ToStr() return str(value) # ok all finished, force compute def GetBuffer(self): # Force compute self.Compute() while len(self.buf) > 1: self.Compute() if self.type == 'Logic': return self.buf[0] if self.type == 'Numeric': return self.SafeEval(self.buf[0]) if self.type == 'Bool': if self.SafeEval(self.buf[0].replace('True', '1').replace('False', '0')): return True else: return False if self.type == None: return '' return self.buf[0] # WARNING : Take care if you edit this function, eval is realy unsafe. # better to use ast.literal_eval() but not implemented before python 3 def SafeEval(self, str): if not str: raise Exception('Nothing to eval') f = re.search('[^0-9+-.\(\)<>=&%!*\^\/]', str) if f: raise Exception('Wrong parameter to Eval : ' + str) return 0 str = str.replace('!', 'not ') # str = str.replace('=', '==') # print('>>' + str) return eval(str) class fonction(object): def __init__(self, name, param, data, c=False): self.name = name self.code = data self.param = param self.const = c def ToStr(self): return 'function ' + self.name + '(' + str(self.param)[1:-1] + ') {' + self.code + '}' class Hack(object): def __init__(self, var): self.var = var def text(self): return self.var class JsParserHelper1(object): def __init__(self, tmp_var): self.reset() self.used = False self.Tmp_var = tmp_var self.op = None def reset(self): type = None self.name = None self.t = None self.arg = None self.rest_code = '' # self.op = None self.eval = False self.property = False def process(self, JScode): # IDK why ? if self.op: return False self.reset() self.at1 = None # If already started if JScode.startswith(self.Tmp_var): self.name = self.Tmp_var else: # si on a rien encore trouve on recherche une variable/fonction r = re.search('^(\w[\w]*)', JScode) if r and not self.used: self.name = r.group(1) else: return False self.used = True # By defaut self.t = 'var' JScode = JScode[(len(self.name)):] c, p = GetNextUsefullchar(JScode) while (c in '.[') and c and not self.at1: JScode = JScode[p:] if c == '[': a = GetItemAlone(JScode, ']') JScode = JScode[(len(a)):] self.at1 = a[1:-1] self.eval = True if c == '.': a = GetItemAlone(JScode[1:], '[(.\/*-+{}<>|=~^%!') JScode = JScode[(len(a)+1):] self.at1 = a self.property = True c, p = GetNextUsefullchar(JScode) if c == '(': a = GetItemAlone(JScode, ')') JScode = JScode[(len(a)):] self.arg = a[1:-1] self.t = 'fct' # operation ? if not self.t == 'fct': m = re.search('^(' + REG_OP + '|\[|$)', JScode, re.UNICODE) if m and JScode: self.op = m.group(1).strip() if self.op == '[': self.op = None else: # prb because the only possible case is == if len(self.op) > 1 and self.op[0] == '=' and not self.op[1] == '=': self.op = self.op[0] JScode = JScode[(len(self.op)):] if self.t == 'fct': out('Fonction :' + self.name + ' method: ' + str(self.at1) + ' arg: ' + self.arg) elif self.t == 'var': if self.property: self.at1 = '"' + self.at1 + '"' out('Variable :' + self.name + ' []= ' + str(self.at1) ) # Exit if nothing to process if (self.name == self.Tmp_var) and not self.at1 and not self.op: return False if self.op: out('operation :' + self.name + ' []= ' + str(self.at1) + ' op: ' + str(self.op) ) self.rest_code = JScode return True class JsParser(object): def __init__(self): self.Unicode = False self.HackVars = [] self.debug = False self.LastEval = '' self.SpecialOption = '' self.Return = False self.ReturnValue = None self.Break = False self.continu = False self.FastEval_vars = [] self.FastEval_recur = 0 self.option_ForceTest = False def SetReturn(self, r, v): self.Return = True self.RecursionReturn = r self.ReturnValue = v def SetOption(self, option): if option == 'ForceTest': self.option_ForceTest = True def AddHackVar(self, name, value): self.HackVars.append((name, value)) def GetVarHack(self, name): return self.GetVar(self.HackVars, name) def PrintVar(self, vars): for i, j in vars: print(i + ' : ' + str(j)) # Need to take care at chain var with " and ' def ExtractFirstchain(self, string): # print(string.encode('ascii', 'replace')) if not len(string.strip()): return '', 0 l = len(string) string = string + ' ' # To prevent index out of range, hack i = -1 p = 0 # parenthese a = 0 # accolade b = 0 # bracket f = False # fonction ? r = False # Regex com1 = False com2 = False prev = '' # previous char c1 = 0 # string with " c2 = 0 # string with ' stringR = '' while l > i: i += 1 # ignore comment if string[i:(i+2)] == '/*': com1 = True if com1: if string[i:(i+2)] == '*/': com1 = False i += 1 continue if string[i:(i+2)] == '//' and not r: com2 = True if com2: if string[i] == '\n': com2 = False else: continue ch = string[i] # if ch == '"' and not GetPrevchar(string,i) == '\\' and not c2: if ch == '"' and not c2: c1 = 1 - c1 if ch == "'" and not c1: c2 = 1 - c2 # if we are in a chain no more thing to do than waiting for end if c1 or c2: stringR = stringR + ch continue if ch == '(': p += 1 if ch == ')': p -= 1 if ch == '{': a += 1 if ch == '}': a -= 1 if ch == '[': b += 1 if ch == ']': b -= 1 if r and ch == '/': r = False if ch == '/' and prev == '=': r = True # vire espace inutile if ch.isspace() and not c1 and not c2: if not(prev in ALPHA and GetNextchar(string, i) in ALPHA): continue stringR = stringR + ch # memorise last char if not ch.isspace(): prev = ch # Dans tout les cas les parenthses doivent etre fermees, ainsi que les crochet if not p and not b: # Si on rencontre un ; par defaut if (ch == ';') and not f: # Ok, accolade fermees aussi, c'est tout bon if not a: return stringR, i # Accoloade non fermee, c'est une fonction else: f = True # si c'est une fonction et l'accolade fermee if f and not a: # quel est le caractere suivant ? j = i + 1 while (string[j].isspace()) and (l > j): j += 1 # Si parenthese on repart if string[j] == '(': continue # Mal formated string ? # Sometime, coder forget the last ; before the } # Desactived for the moment, because can bug in 'a = {};' if False: j = -2 while (stringR[j].isspace()) or (stringR[j] == '}'): j -= 1 if not (stringR[j] == ';'): j += 1 stringR = stringR[:j] + ';' + stringR[j:] # if there is a last ; add it if string[i+1] == ';': stringR = stringR + ';' i += 1 return stringR, i # chaine bugguée ? if ';' not in string: # out('ERROR Extract chain without ";" > ' + string) return string.rstrip() + ';', i raise Exception("Can't extract chain " + string) # Everything Without a "Real" is False def CheckTrueFalse(self, string): # out('> Check True or false : ' + str(string)) if isinstance(string, bool): if string == True: return True elif isinstance(string, types.StringTypes): if not string == '': return True if isinstance(string, (int, long, float)): if not (string == 0): return True if isinstance(string, (list, tuple)): if not (string == []): return True return False # Syntax > aaaaaa.bbbbbb(cccccc) ou bbbb(cccc) ou "aaaa".bb(ccc) ou aa[bb](cc) def FonctionParser(self, vars, allow_recursion, name, function, arg2, JScode): arg = arg2.strip() out('fonction > Name: ' + Ustr(name) + ' arg: ' + Ustr(arg) + ' function: ' + Ustr(function)) # hack ? if isinstance(name, Hack): a = MySplit(arg, ',', True) # In this case function = text but useless ATM if a: # ecriture vv = self.evalJS(a[0], vars, allow_recursion) self.AddHackVar(name.var, vv) return vv, JScode else: # lecture vv = self.GetVarHack(name.var) out('Hack vars (set): ' + vv) return vv, JScode # Definite function ? fe = self.IsFunc(vars, function) if not fe: try: fe = self.IsFunc(vars, '%s["%s"]' % (name, function)) except: pass if fe: if fe == '$': a = MySplit(arg, ',', True) vv = self.evalJS(a[0], vars, allow_recursion) fff = Hack(vv) return fff, JScode elif isinstance(fe, types.MethodType): # print(fe.im_func.__name__) # parseint # print(fe.im_class.__name__) # Basic function = fe.im_func.__name__ out("> function (native): " + function + ' arg=' + arg) # and continu with native fonction elif isinstance(fe, fonction): out('> fonction definie par code : ' + function) n, p, c, ct = fe.name, fe.param, fe.code, fe.const a = MySplit(arg, ',', True) a2 = [] # out('code de la fonction : ' + c) if ct: out('constructor mode') # hack # Make replacement JScode = "%s(%s)%s" % (n, arg, JScode) + ';' NewEval = self.Parse(JScode, vars, allow_recursion) return NewEval, '' for i in a: vv = self.evalJS(i, vars, allow_recursion) a2.append(RemoveGuil(vv)) List_tmpvar = [] if (len(p) > 0) and (len(a2) > 0): nv = tuple(zip(p, a2)) for z, w in nv: self.SetVar(vars, z, w) List_tmpvar.append(z) jjj = self.Parse(c, vars, allow_recursion) # And delete tmp var for i in List_tmpvar: self.InitVar(vars, i) if self.Return: self.Return = None # return jjj, JScode return self.ReturnValue, JScode else: raise Exception("Strnage fonction") # Native fonction # http://stackoverflow.com/questions/1091259/how-to-test-if-a-class-attribute-is-an-instance-method s = '' if type(name) in [list, tuple, dict, types.MethodType, NoneType]: s = name else: if name.startswith('"') or name.startswith("'"): s = RemoveGuil(name) else: if self.IsVar(vars, name): s = self.GetVar(vars, name) else: s = name for lib in List_Lib: if hasattr(lib, function): if not function == 'eval': arg = MySplit(arg, ',') for i in range(len(arg)): arg[i] = self.evalJS(arg[i], vars, allow_recursion) # for fastcall self.FastEval_vars = vars self.FastEval_recur = allow_recursion cls = lib(self, s) r = getattr(cls, function)(arg) # set new value if changed if hasattr(lib, 'Get'): NV = getattr(cls, 'Get')() if not NV == s: self.SetVar(vars, name, NV) return r, JScode # test, if all is ok, never reached if False: # function if function == 'function': pos9 = len(JScode) v = self.MemFonction(vars, '', arg, False, JScode)[2] JScode = JScode[pos9:] return v, JScode # constructor if function == 'Function': NewCode = RemoveGuil(arg) + ';' v = self.MemFonction(vars, '', '', False, '{' + NewCode + '}')[2] JScode = v + JScode NewEval = self.Parse(JScode, vars, allow_recursion) return NewEval, '' self.PrintVar(vars) raise Exception('Unknow fonction : ' + function) def Fast_Eval(self, strg): r = self.evalJS(strg, self.FastEval_vars, self.FastEval_recur) return r def VarParser(self, vars, allow_recursion, variable, op, JScode): New_Var = False out('Variable : ' + str(variable) + ' operator : ' + op) # if it's a creation/modification if op == '=': out('creation/modification') v1 = GetItemAlone(JScode, ',') JScode = JScode[(len(v1)):] v1 = v1.strip() self.VarManage(allow_recursion, vars, variable, v1) # and return it r = self.GetVar(vars, variable) return r, JScode if not self.IsVar(vars, variable): raise Exception("Cannot find var " + str(variable)) r = self.GetVar(vars, variable) # Only modification if len(op) == 2: # just put var because not managed here if op[0] in '=!': return r, op + JScode # ok so what is it ? out('> var ' + variable + '=' + str(r)) # check if it's i++ ou i -- form if op == '++': self.SetVar(vars, variable, r + 1) return r, JScode elif op == '--': self.SetVar(vars, variable, r-1) return r, JScode # a += 1 form elif op[1] == '=' and op[0] in '+-*/%^': n = GetItemAlone(JScode, ';,') out('A rajouter ' + n) r = self.evalJS(variable + op[0] + n, vars, allow_recursion) # self.SetVar(vars, variable, r) if isinstance(r, (int, long, float)): self.VarManage(allow_recursion, vars, variable, str(r)) if isinstance(r, str): self.VarManage(allow_recursion, vars, variable, '"' + r + '"') else: self.VarManage(allow_recursion, vars, variable, str(r)) JScode = JScode[(len(n)):] return r, JScode # just var # re-ad op if not used JScode = op + JScode return r, JScode def evalJS(self, JScode, vars, allow_recursion): if allow_recursion < 0: raise Exception('Recursion limit reached') allow_recursion -= 1 # plus que la chaine a evaluer JScode = JScode.strip() out('-------------') out(str(allow_recursion) + ' : A evaluer >' + JScode + '<\n') # ******************************************************** InterpretedCode = JSBuffer() while len(JScode) > 0: c = JScode[0] # print('InterpretedCode > ' + InterpretedCode) out('JScode > ' + JScode.encode('ascii', 'replace') + '\n') # parentheses if c == '(': c2 = GetItemAlone(JScode, ')')[1:-1] pos2 = len(c2) + 2 JScode = JScode[pos2:] v = self.evalJS(c2, vars, allow_recursion) self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), v) JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode # remove "useless" code if JScode.startswith('new '): JScode = JScode[4:] continue # in operator if JScode[0:2] == 'in': A = InterpretedCode.GetPrevious() B = GetItemAlone(JScode[2:], ',;&|') B2 = self.evalJS(B, vars, allow_recursion) if type(B2) in [types.MethodType, types.InstanceType]: B2 = str(B2) if A in B2: InterpretedCode.AddValue(True) else: InterpretedCode.AddValue(False) JScode = JScode[(len(B) + 2):] continue # Special value m = re.search('^(true|false|null|String)', JScode, re.UNICODE) if m: v = m.group(1) JScode = JScode[len(v):] if v == 'true': InterpretedCode.AddValue(True) if v == 'false': InterpretedCode.AddValue(False) if v == 'null': InterpretedCode.AddValue(None) if v == 'String': self.SetVar(vars, 'TEMPORARY_VARS ' + str(allow_recursion), '') JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode # if v == 'Array': # InterpretedCode.AddValue([]) continue # hackVars r = re.search('^\$\("#([\w]+)"\)\.text\(\)', JScode) if r: InterpretedCode.AddValue(self.GetVar(self.HackVars, r.group(1))) JScode = JScode[(r.end()):] continue if JScode[0] == '$': InterpretedCode.AddValue('$') JScode = JScode[1:] continue # new function delcaration ? Need to be before the fonction/variable parser. # var x = function (a, b) {return a * b}; # function myFunction(a, b) {return a * b}; if JScode.startswith('function'): m = re.search(r'^function(?: ([\w]+))* *\(([^\)]*)\) *{', JScode, re.DOTALL) if m: name = '' openparenthesis = False if m.group(1): name = m.group(1) replac, pos3, v = self.MemFonction(vars, name, m.group(2), openparenthesis, JScode) JScode = replac InterpretedCode.AddValue(v) continue # pointeur vers fonction ? if hasattr(Basic, JScode): fm = getattr(Basic(self, None), JScode) InterpretedCode.AddValue(fm) JScode = '' continue # 3 - numeric chain r = re.search('(^(?:0x)*[0-9]+)', JScode) if r: v = JScode[0:r.end()] if v.startswith('0x'): v = int(v, 0) else: v = int(v) InterpretedCode.AddValue(v) JScode = JScode[(r.end()):] continue # for this one continue directly # 4 - Regex r = re.search('^\/.*\/(.*$)', JScode) if r: reg = r.group(0) flag = r.group(1) # test if the regex is valid if flag: for i in flag: if i not in 'gimuy': reg = None break InterpretedCode.AddValue(reg) JScode = JScode[(len(r.group(0))):] continue # return directly # 1 - Array / method if c == '[': c2 = GetItemAlone(JScode, ']')[1:-1] pos2 = len(c2) + 2 # v = self.evalJS(c2,vars,allow_recursion) # all this part is managed away but not for some rare case. A = InterpretedCode.GetPrevious() if not A: valueT = MySplit(c2, ',', True) JScode = JScode[pos2:] InterpretedCode.AddValue(valueT) continue # other case self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), A) JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode # 2 - Alpha chain elif c == '"' or c == "'": ee = GetItemAlone(JScode, c) e = len(ee) vv = ee[1:-1] # raw string cannot end in a single backslash # if vv[-1:] == '\\' and not vv[-2:-1] == '\\': # vv = vv + '\\' # warning with this function # if not vv.endswith('\\'): # vv = vv.decode('string-escape') JScode = JScode[e:] # to be faster if len(JScode) == 0: InterpretedCode.AddValue(vv) continue # normal way else: self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), vv) JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode item = '' # 5 Variable/fonction/object P1 = JsParserHelper1('TEMPORARY_VARS' + str(allow_recursion)) while P1.process(JScode): JScode = P1.rest_code r = None if P1.t == 'var': # special vars if P1.name == 'window' and P1.at1: P1.name = RemoveGuil(P1.at1) P1.at1 = '' Var_string = P1.name if P1.at1: Var_string = "%s[%s]" % (P1.name, str(P1.at1)) # operation / creation ? if P1.op: out('creation/modification ' + Var_string + ' ' + P1.op) r, JScode = self.VarParser(vars, allow_recursion, Var_string, P1.op, JScode) else: if not self.IsVar(vars, P1.name): self.PrintVar(vars) raise Exception('Variable error : ' + P1.name) r = self.GetVar(vars, Var_string) elif P1.t == 'fct': if P1.at1: fonction = P1.at1 name = P1.name else: fonction = P1.name name = '' if P1.eval: fonction = self.evalJS(fonction, vars, allow_recursion) # hack, devrait etre acive tout le temps if 'TEMPORARY_VARS' in name: name = self.evalJS(name, vars, allow_recursion) gg = fonction + '***' + P1.arg + '**' + JScode r, JScode = self.FonctionParser(vars, allow_recursion, name, fonction, P1.arg, JScode) # to speed up if not JScode: # It speed up but cause some TEMPORARY_VARS stay in code. InterpretedCode.AddValue(r) continue # normal way else: self.SetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion), r) JScode = 'TEMPORARY_VARS' + str(allow_recursion) + JScode # after this part, all TEMPORARY_VARS need to be removed if JScode.startswith('TEMPORARY_VARS' + str(allow_recursion)): r = self.GetVar(vars, 'TEMPORARY_VARS' + str(allow_recursion)) self.InitVar(vars, 'TEMPORARY_VARS' + str(allow_recursion)) JScode = JScode[(len('TEMPORARY_VARS' + str(allow_recursion))):] InterpretedCode.AddValue(r) continue if P1.used: continue # --var method, HACK if JScode[0:2] == '--' or JScode[0:2] == '++': m = re.search('^(\({0,1}\w[\w\.]*\){0,1} *(?:\[[^\]]+\])* *)(' + REG_OP + '|\[|$)', JScode[2:], re.UNICODE) if m: l = len(m.group(1)) JScode = m.group(1) + JScode[0:2] + JScode[(l+2):] continue else: bb(mm) # Space to remove if c == ' ' or c == '\n': JScode = JScode[1:] continue # Escape char if c == '\\': JScode = JScode[1:] continue # Special if (A)?(B):(C) if c == '?': out(" ****** Special if 1 ********* ") # need to find all part A = InterpretedCode.GetPrevious() B = GetItemAlone(JScode, ':') C = GetItemAlone(JScode[(len(B) + 1):]) Totlen = len(B) + len(C) + 2 B = B[1:] if B.startswith('('): B = B[1:-1] if C.startswith('('): C = C[1:-1] if A: r = self.evalJS(B, vars, allow_recursion) else: r = self.evalJS(C, vars, allow_recursion) InterpretedCode.AddValue(r) JScode = JScode[Totlen:] continue # Short-circuiting evaluations if JScode[0:2] == '&&' or JScode[0:2] == '||': out(" ****** Short-circuiting ********* ") A = InterpretedCode.GetPrevious() B = GetItemAlone(JScode[2:]) Totlen = len(B) + 2 if B.startswith('('): B = B[1:-1] # for && if the first operand evaluates to false, the second operand is never evaluated if JScode[0:2] == '&&': if A: r = self.evalJS(B, vars, allow_recursion) InterpretedCode.AddValue(r) else: InterpretedCode.AddValue(A) # for || if the result of the first operand is true, the second operand is never operated if JScode[0:2] == '||': if not A: r = self.evalJS(B, vars, allow_recursion) InterpretedCode.AddValue(r) else: InterpretedCode.AddValue(A) JScode = JScode[Totlen:] continue # Operation if c in '+<>-*/=&%|!^.': InterpretedCode.SetOp(c) JScode = JScode[1:] continue # No sure how to put this if JScode == '{}': InterpretedCode.AddValue({}) JScode = JScode[2:] continue if JScode == '[]': InterpretedCode.AddValue([]) JScode = JScode[2:] continue # ??? if JScode == ';': JScode = JScode[1:] continue # comma if c == ',': InterpretedCode.GetPrevious() JScode = JScode[1:] continue # Not found part # We will make another turn self.PrintVar(vars) out("Can't eval string :" + JScode) out('Last eval : ' + str(self.LastEval)) # print(debug.encode('ascii', 'replace')) raise Exception(str(allow_recursion) + " : Cannot Eval chain : " + JScode) InterpretedCode2 = InterpretedCode.GetBuffer() out(str(allow_recursion) + ' : Evalue > ' + Ustr(InterpretedCode2) + ' type ' + Ustr(type(InterpretedCode2))) out('-------------') self.LastEval = InterpretedCode2 return InterpretedCode2 def InitVar(self, var, variable): variable = variable.strip() for j in var: if j[0] == variable: var.remove(j) return def GetVar(self, var, variable): # variable = variable.strip() index = None if '[' in variable: index = GetItemAlone(variable[(variable.find('[')):], ']') index = index[1:-1] variable = variable.split('[')[0] index = self.evalJS(index, var, 50) if '.' in variable: index = variable.split('.')[1] variable = variable.split('.')[0] # out('Variable Get ' + variable + ' index :' + str(index)) for j in var: if j[0] == variable: k = j[1] r = k if not (index == None): # Special method if index == 'length': r = len(k) return r if index == 'constructor': return GetConstructor(k) if type(k) in [list, tuple, str]: if CheckType(index) == 'Numeric': if int(index) < len(k): r = k[int(index)] else: r = 'undefined' elif CheckType(index) == 'String': index = RemoveGuil(index) try: r = k[index] except: r = k[int(index)] elif type(k) in [dict]: index = RemoveGuil(index) r = k.get(index) elif type(k) in [type]: r = getattr(k(self, None), index) return r # search it in hackvar ? for j in self.HackVars: if j[0] == variable: return j[1] raise Exception('Variable not defined: ' + str(variable)) def SetVar(self, var, variable, value, i=None): variable = variable.strip() # Existing var ? for j in var: if j[0] == variable: if i == None: # vars ? if isinstance(value, types.StringTypes): var[var.index(j)] = (variable, value) # Numeric else: var[var.index(j)] = (variable, value) else: # Array if type(var[var.index(j)][1]) in [list, tuple]: Listvalue = var[var.index(j)][1] # ok this place doesn't esist yet l = int(i) - len(Listvalue) + 1 while l > 0: Listvalue.append('undefined') l -= 1 # Now modify it if type(value) in [list, tuple]: Listvalue = value else: Listvalue[int(i)] = value var[var.index(j)] = (variable, Listvalue) # dictionnary elif type(var[var.index(j)][1]) in [dict]: Listvalue = var[var.index(j)][1] Listvalue[i] = value var[var.index(j)] = (variable, Listvalue) return # New var var.append((variable, value)) def GetTypeVar(self, var, variable): try: variable = variable.split('[')[0] variable = variable.split('.')[0] for j in var: if j[0] == variable: return type(j[1]) return 'Undefined' except: return 'Undefined' def IsVar(self, var, variable, index=None): try: variable = variable.split('[')[0] variable = variable.split('.')[0] for j in var: if j[0] == variable: if index == None: return True if index in var[var.index(j)][1]: return True return False except: return False # Need to use metaclass here def IsFunc(self, vars, name): bExist = False bExist = self.IsVar(vars, name) if not bExist: return False f = self.GetVar(vars, name) if f == '$': return '$' if isinstance(f, fonction): return f elif isinstance(f, types.MethodType): return f else: return self.IsFunc(vars, f) def VarManage(self, allow_recursion, vars, name, value=None): index = None init = False try: value = value.strip() except: pass name = name.strip() # variable is an object if '.' in name: if self.GetTypeVar(vars, name) == 'tuple': index = name.split('.')[1] name = name.split('.')[0] # Variable is an array ? m = re.search(r'^\({0,1}([\w]+)\){0,1}\[(.+?)\]$', name, re.DOTALL | re.UNICODE) if m: name = m.group(1) index = m.group(2) index = self.evalJS(index, vars, allow_recursion) if value: if isinstance(value, (int, long, float)): value = self.evalJS(value, vars, allow_recursion) else: # Values is an array [] if value.startswith('[') and value.endswith(']'): value = value[1:-1] # hack if value == '': value = [] # normal way else: valueT = MySplit(value, ',') v = [] for k in valueT: v2 = self.evalJS(k, vars, allow_recursion) v.append(v2) value = v if index == None: index = 0 init = True # Values is an array {} elif value.startswith('{') and value.endswith('}'): value = value[1:-1] valueT = MySplit(value, ',', True) v = {} for k in valueT: l = k.split(':') # WARNING : no eval here in JS v2g = RemoveGuil(l[0]) v2d = self.evalJS(l[1], vars, allow_recursion) v[v2g] = v2d value = v if index == None: index = 0 init = True # string and other else: value = self.evalJS(value, vars, allow_recursion) name = name.strip() # Output for debug if not (index == None): out('> Variable in parser => ' + Ustr(name) + '[' + Ustr(index) + ']' + ' = ' + Ustr(value)) else: out('> Variable in parser => ' + Ustr(name) + ' = ' + Ustr(value)) # chain if isinstance(value, types.StringTypes): self.SetVar(vars, name, value, index) # number elif isinstance(value, (int, long, float)): self.SetVar(vars, name, value, index) # list elif type(value) in [list, tuple, dict]: if init: self.InitVar(vars, name) self.SetVar(vars, name, value, index) # fonction elif isinstance(value, fonction): self.SetVar(vars, name, value, index) # undefined elif value == None: self.SetVar(vars, name, None, index) else: print(type(value)) raise Exception('> ERROR : Var problem >' + str(value)) return def MemFonction(self, vars, name, parametres, openparenthesis, data): if not name: n0 = 0 while self.IsFunc(vars, 'AnonymousFunc' + str(n0)): n0 = n0 + 1 name = 'AnonymousFunc' + str(n0) if self.SpecialOption: if self.SpecialOption.split('=')[0] == 'Namefunc': name = self.SpecialOption.split('=')[1] self.SpecialOption = '' param = MySplit(parametres, ',', True) out('Extract function :' + name + ' ' + str(param)) pos = 0 replac = '' while not data[0] == '{': data = data[1:] content = GetItemAlone(data, '}')[1:-1] pos2 = len(content) + 1 fm = fonction(name, param, content.lstrip()) self.SetVar(vars, name, fm) data = data[(pos2 + 1):] if openparenthesis: c, p = GetNextUsefullchar(data) if c == ')': data = data[(p + 1):] openparenthesis = False selfinvoked = False if len(data) > 0: if data[0] == '(': selfinvoked = True # self invoked ? if selfinvoked: paraminvoked = GetItemAlone(data, ')') out('Self invoked ' + str(paraminvoked)) replac = name + paraminvoked data = data[(len(paraminvoked)):] if openparenthesis: c, p = GetNextUsefullchar(data) if c == ')': data = data[(p + 1):] openparenthesis = False replac = replac + data return replac, 0, name def Parse(self, JScode, vars, allow_recursion=MAX_RECURSION): if allow_recursion < 0: raise Exception('Recursion limit reached') allow_recursion -= 1 # ************************ # Post traitement # ************************ # Need all functions first, because they can be called first and be at the bottom of the code # So we extract all functions first, and replace them by a simple call in the code, if they are self invoked # Make this part only if needed if 'function' in JScode: posG = 0 while True: chain, pos = self.ExtractFirstchain(JScode[posG:]) if not chain: break Startoff = posG Endoff = posG + pos + 1 posG = Endoff # skip empty char chain = chain.strip() # fonction m = re.search(r'^(\()* *function(?: ([\w]+))* *\(([^\)]*)\) *{', chain, re.DOTALL) if m: name = '' openparenthesis = False if m.group(2): name = m.group(2) if m.group(1): openparenthesis = True replac, pos3, xyz = self.MemFonction(vars, name, m.group(3), openparenthesis, chain) JScode = JScode[:Startoff] + replac + JScode[Endoff:] posG = Startoff + len(replac) # *********************** # The real Parser # ********************** Parser_return = None while True: if self.continu: break chain, pos = self.ExtractFirstchain(JScode) if not chain: break JScode = JScode[(pos + 1):] chain = chain.lstrip().rstrip() # empty ? if chain == ';': continue out('D++++++++++++++++++') out(chain.encode('ascii', 'replace')) out('F++++++++++++++++++') # hackVars ? m = re.search(r'^\$\("#([^"]+)"\)\.text\(([^\)]+)\);', chain) if m: out('> hack ' + m.group(0) + ' , variable est ' + m.group(1)) self.SetVar(self.HackVars, m.group(1),self.GetVar(vars, m.group(2))) continue # break if chain.startswith('break'): self.Break = True return # continue if chain.startswith('continue'): self.continu = True return # Return ? if chain.startswith('return'): m = re.match(r'return *;', chain) if m: self.Return = True self.ReturnValue = None return None m = re.match(r'^return *([^;]+)', chain) if m: chain = m.group(1) r = self.evalJS(chain, vars, allow_recursion) self.Return = True self.ReturnValue = r return self.ReturnValue # Variable creation/modification ? if chain.startswith('var '): out('var') chain = chain[4:] # Now need to extract all vars from chain while chain: v1 = GetItemAlone(chain, ',').strip() chain = chain[(len(v1) + 1):] if v1.endswith(',') or v1.endswith(';'): v1 = v1[:-1] self.evalJS(v1, vars, allow_recursion) continue name = '' # Extraction info # Problem, catch fonction too :( m = re.search(r'^([\w]+) *(\(|\{)', chain, re.DOTALL) # Syntax > aaaaa(bbbbb) ......... if m: name = m.group(1) sp = m.group(2) if sp == '(': arg = GetItemAlone(chain[(m.end()-1):], ')')[1:-1] pos3 = len(arg) + 1 code = chain[(m.end() + pos3):] elif sp == '{': arg = '' code = chain[(m.end()-1):] else: raise Exception('> Er 74') out('DEBUG > Name: ' + name + ' arg: ' + arg + ' code: ' + code + '\n') # Jquery if name == 'DOCUMENT_READY': out('DOCUMENT_READY ' + arg) self.SpecialOption = 'Namefunc=DR' self.Parse(arg, vars, allow_recursion) # It's not the correct place to do that, but for the moment ... self.Parse('DR();', vars, allow_recursion) continue # For boucle ? if name == 'for': arg = arg.split(';') v = arg[0] + ';' t = arg[1] i = arg[2] + ';' f = code if GetNextUsefullchar(f)[0] == '{': f = GetItemAlone(f, '}')[1:-1] # init var self.Parse(v, vars, allow_recursion) # loop while self.CheckTrueFalse(self.evalJS(t, vars, allow_recursion)): # fonction self.Parse(f, vars, allow_recursion) if self.Break: self.Break = False break # incrementation self.Parse(i, vars, allow_recursion) continue # boucle while ? if name == 'while': f = code if GetNextUsefullchar(f)[0] == '{': f = GetItemAlone(f, '}')[1:-1] # loop while self.CheckTrueFalse(self.evalJS(arg, vars, allow_recursion)): # fonction self.Parse(f, vars, allow_recursion) if self.Break: self.Break = False break if self.continu: self.continu = False continue # boucle do/while if name == 'do': f = code e = '' if sp == '{': f = GetItemAlone(f, '}') if f.startswith('{'): f = f[1:-1] # Need to check the while part ? chain2, pos2 = self.ExtractFirstchain(JScode) if 'while' in chain2: chain2 = chain2.lstrip() JScode = JScode[(pos2 + 1):] m2 = re.search(r'while\s*\((.+?)\);$', chain2, re.DOTALL) if m2: e = m2.group(1) if not e: raise Exception('> While error') out('> Boucle do/while : test :' + e + ' code: ' + f) # loop # 1 forced execution because do/while self.Parse(f, vars, allow_recursion) if self.Break: self.Break = False continue # stop all if self.continu: self.continu = False # and now the loop while self.CheckTrueFalse(self.evalJS(e, vars, allow_recursion)): # fonction self.Parse(f, vars, allow_recursion) if self.Break: self.Break = False break if self.continu: self.continu = False continue # boucle switch if name == 'switch': v = self.evalJS(arg, vars, allow_recursion) f = code[1:] if v == 'undefined': continue # Search the good case code StrToSearch = "case%s:" % (str(v)) while (not f.startswith(StrToSearch)) and (len(f) > 0): tmp_str = GetItemAlone(f, ';}') f = f[(len(tmp_str) + 1):] if len(f) < 1: self.PrintVar(vars) raise Exception("Can't find switch value " + str(v)) f = f[(len(StrToSearch)):] self.Parse(f, vars, allow_recursion) continue # Boucle if if name == 'if': t = arg f = code e = '' if GetNextUsefullchar(f)[0] == '{': f = GetItemAlone(f, '}')[1:-1] # Need to check if there is else statement ? chain2, pos2 = self.ExtractFirstchain(JScode) if 'else' in chain2: chain2 = chain2.lstrip() JScode = JScode[(pos2 + 1):] m2 = re.search(r'else\s*{(.+?)}$', chain2, re.DOTALL) if m2: e = m2.group(1) # hack, need to memorise working test in future if self.option_ForceTest: try: ttt = self.CheckTrueFalse(self.evalJS(t, vars, allow_recursion)) except: from random import choice ttt = choice([True, False]) # thx to come every day, to help me to find bug on this code if ttt: self.Parse(f, vars, allow_recursion) elif e: self.Parse(e, vars, allow_recursion) continue # normal way else: if self.CheckTrueFalse(self.evalJS(t, vars, allow_recursion)): self.Parse(f, vars, allow_recursion) elif e: self.Parse(e, vars, allow_recursion) continue if name == 'with': f = code if GetNextUsefullchar(f)[0] == '{': f = GetItemAlone(f, '}') # list all arg membre. member_list = self.GetVar(vars, arg) out('> With fonction : exp=' + arg + ' values=' + str(member_list)) # print('Before: ' + f) # print(member_list) def sub(g): g = g.group() return g[0] + arg + '["' + g[1:-1] + '"]' + g[-1:] # Hack again if type(member_list) in [type]: for i in member_list.__dict__: f = re.sub(r'[^\w]' + str(i) + '[^\w]', sub, f, re.DOTALL) else: for i in member_list: f = re.sub(r'[^\w]' + i + '[^\w]', sub, f, re.DOTALL) # print('after: ' + f) self.Parse(f[1:-1], vars, allow_recursion) # JScode = f[1:-1] + ';' + JScode continue # Pas trouve, une fonction ? if chain.endswith(';'): Parser_return = self.evalJS(chain[:-1], vars, allow_recursion) # hack # if 'return "ok"' in str(Parser_return): # JScode = str(Parser_return) # continue # hack, need to be reenabled # Non gere encore if not chain.endswith(';'): print('> ' + JScode) raise Exception('> ERROR : Cannot parse >' + chain) return Parser_return def ProcessJS(self, JScode, vars=[]): vars_return = [] # unicode ? if False: out('Unicode convertion') JScode = unicode(JScode, 'utf-8') self.Unicode = True # Special vars.append(('Math', Math)) vars.append(('String', '')) vars.append(('document', {'write': 'ok'})) # Hack JScode = JScode.replace('$(document).ready', 'DOCUMENT_READY') # Start the parsing ret = self.Parse(JScode, vars) # Memorise vars return ret # --------------------------------------------------------------------------------------------------------------------- # fonctions # def toStr(str): def decorator(f): class _temp: def __call__(self, *args, **kwargs): return f(self.real_self, *args, **kwargs) def __str__(self): return str % f.__name__ return _temp() return decorator class Math(object): def __init__(self, initV1, initV2): pass def max(self, arg): t1 = arg[0] t2 = arg[1] return max(t1, t2) def min(self, arg): t1 = arg[0] t2 = arg[1] return min(t1, t2) def abs(self, arg): return abs(arg[0]) def pow(self, arg): t1 = arg[0] t2 = arg[1] return pow(t1, t2) @toStr('function %s() {\n [native code]\n}') def sin(self, arg): return math.sin(arg[0]) @toStr('function %s() {\n [native code]\n}') def atan(self, arg): return math.atan(arg[0]) def __contains__(self, arg): if arg in ['max', 'min', 'abs', 'pow', 'sin', 'atan']: return True return False class String(object): def __init__(self, initV1, initV2=''): self._JSParser = initV1 self._string = initV2 def Get(self): return self._string def charCodeAt(self, arg): v = arg[0] return ord(self._string[int(v)]) def length(self, arg): return len(self._string) def substring(self, arg): p1 = arg[0] if len(arg) > 1: p2 = arg[1] return self._string[int(p1): int(p2)] else: return self._string[int(p1):] def replace(self, arg): t1 = arg[0] t2 = arg[1] # if not t1.startswith('/'): # t1 = self.evalJS(t1,vars,allow_recursion) # regex mode ? HACK if t1.startswith('/'): jr = re.findall(t1.split('/')[1], self._string) for k in jr: if not self._JSParser.IsFunc(self._JSParser.FastEval_vars, t2): self._string = self._string.replace(k, t2) out('Replace (F) ' + str(k) + ' by ' + str(t2)) else: v = self._JSParser.Fast_Eval(t2 + '(' + k + ')') v = str(v) self._string = self._string.replace(k, v) out('Replace ' + str(k) + ' by ' + str(v)) # String mode else: # t1 = self.evalJS(t1, vars, func, allow_recursion) self._string = s.replace(t1, t2) return self._string def fromCharCode(self, arg): return chr(int(arg[0])) def split(self, arg): arg = arg[0].replace('"', '').replace("'", "") if arg == '': return list(self._string) else: return self._string.split(arg) def indexOf(self, arg): start = 0 if len(arg) > 1: start = int(arg[1]) return self._string.find(arg[0], start) class Array(object): def __init__(self, initV1, initV2=[]): self._array = initV2 def Get(self): return self._array def join(self, arg): t = arg[0].replace('"', '').replace("'", "") return t.join(self._array) def push(self, arg): t1 = arg[0] if len(arg) > 1: # use s.extend-[array]) raise Exception('Not implemented - push') self._array.append(t1) v = len(self._array) return v def slice(self, arg): p1 = arg[0] if len(arg) > 1: p2 = arg[1] sr = self._array[int(p1):int(p2)] else: sr = self._array[int(p1):] sr = '"' + sr + '"' return sr def splice(self, arg): t1 = arg[0] t2 = arg[1] if len(arg) > 2: raise Exception('Not implemented - splice') tab = self._array[:t1] + self._array[(t1 + t2):] tabsup = self._array[t1:(t1 + t2)] self._array = tab return tabsup def shift(self, arg): if len(self._array) == 0: return None return self._array.pop(0) class Basic(object): def __init__(self, initV1, initV2): self._JSParser = initV1 self._name = initV2 pass def Setting(self, vars): self._vars = vars def parseInt(self, arg): t1 = arg[0] t2 = arg[1] if t1 == '': return None r = int(t1, int(t2)) return r def typeof(self, arg): return type(arg) def debug(self, arg): print('------------------------------------') self._JSParser.PrintVar(self._JSParser.FastEval_vars) print('------------------------------------') raise Exception('DEBUG') return def eval(self, arg): out('To eval >' + arg) r = self._JSParser.Parse(RemoveGuil(arg), self._JSParser.FastEval_vars, self._JSParser.FastEval_recur) return r def Array(self, arg): if arg[0]: if isinstance(arg[0], (int, long)): return [] return arg return [] def alert(self, arg): # logwrite(str(arg)) print('------------ALERT-------------------') print(arg) print('------------------------------------') return '' def RegExp(self, arg): t1 = RemoveGuil(arg[0]) t2 = RemoveGuil(arg[1]) return '/' + t1 + '/' + t2 # this fonction if for object normaly def toString(self, arg): t1 = arg[0] try: f = self._name.im_func.__name__ except: f = "HACK'" t = 'function %s() {\n [native code]\n}' % f return t List_Lib = [Basic, Array, String, Math]