#!/usr/bin/python # This is a helper script to validate a file for asm.js. # cmdline usage: 'python validate_asmjs.py filename.{html/js}' # Prints a line starting with 'OK: ' on success, and returns process exit code 0. # On failure, prints a line starting with 'FAIL: ', and returns a nonzero process exit code. # python usage: 'validate_asmjs("filename.{html/js}", muteOutput=True/False)' # Returns True/False depending on whether the file was valid asm.js. # This script depends on the SpiderMonkey JS engine, which must be present in PATH in order for this script to function. import subprocess, sys, re, tempfile, os, time import shared # Given a .js file, returns True/False depending on if that file is valid asm.js def validate_asmjs_jsfile(filename, muteOutput): cmd = shared.SPIDERMONKEY_ENGINE + ['-c', filename] if not shared.SPIDERMONKEY_ENGINE or cmd[0] == 'js-not-found' or len(cmd[0].strip()) == 0: print >> sys.stderr, 'Could not find SpiderMonkey engine! Please set tis location to SPIDERMONKEY_ENGINE in your ' + shared.hint_config_file_location() + ' configuration file!' return False try: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) except Exception, e: print >> sys.stderr, 'Executing command ' + str(cmd) + ' failed due to an exception: ' + str(e) + '!' return False (stdout, stderr) = process.communicate() if not muteOutput: if len(stdout.strip()) > 0: print stdout.strip() if len(stderr.strip()) > 0: # Pretty-print the output not to contain a spurious warning. warning_re = re.compile(re.escape('warning: successfully compiled asm.js'), re.IGNORECASE) stderr = warning_re.sub(' successfully compiled asm.js', stderr) print >> sys.stderr, stderr.strip() if 'successfully compiled asm.js' in stderr.lower(): return True else: return False # This tool takes as input a file built with Emscripten (either .html or .js) and validates it for asm.js. # Returns True/False denoting whether the file was valid asm.js. In case of a .html file, all tags are searched, # and the ones containing a "use asm" section are validated. def validate_asmjs(filename, muteOutput): if filename.endswith('.html'): html = open(filename, 'r').read() matches = re.findall('''<\w*script\w*.*?>(.*?)<\w*/script\w*>''', html, re.DOTALL | re.MULTILINE) numAsmJsBlocks = 0 for match in matches: if '"use asm"' in match: numAsmJsBlocks = numAsmJsBlocks + 1 tmp_js = tempfile.mkstemp(suffix='.js') os.write(tmp_js[0], match) os.close(tmp_js[0]) valid_asmjs = validate_asmjs_jsfile(tmp_js[1], muteOutput) os.remove(tmp_js[1]) if not valid_asmjs: return False if numAsmJsBlocks == 0: # Test a .js file with the same basename - emcc convention # is to generate files with same basename but different suffix. js_file = filename.replace('.html', '.js') if os.path.isfile(js_file): return validate_asmjs(js_file, muteOutput) if not muteOutput: print >> sys.stderr, 'Error: the file does not contain any "use asm" modules.' return False else: return True else: return validate_asmjs_jsfile(filename, muteOutput) def main(): if len(sys.argv) < 2: print 'Usage: validate_asmjs ' return 2 if validate_asmjs(sys.argv[1], muteOutput=False): print "OK: File '" + sys.argv[1] + "' validates as asm.js" return 0 else: print "FAIL: File '" + sys.argv[1] + "' is not valid asm.js" return 1 if __name__ == '__main__': sys.exit(main())