1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#!/usr/bin/env python
2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# Copyright (c) 2015 The Chromium Authors. All rights reserved.
3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# Use of this source code is governed by a BSD-style license that can be
4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# found in the LICENSE file.
5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport argparse
7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport os
8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport platform
9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport shutil
10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport subprocess
11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport sys
12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport json
13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport tempfile
14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_V8_DIR = os.path.abspath(
17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    os.path.join(os.path.dirname(__file__), os.path.pardir, 'third_party',
18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                 'v8'))
19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikprint _V8_DIR
21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_JS_PARSER_DIR = os.path.abspath(
23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    os.path.join(os.path.dirname(__file__), os.path.pardir, 'third_party',
24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                 'parse5', 'parse5.js'))
25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_BOOTSTRAP_JS_DIR = os.path.abspath(
28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    os.path.join(os.path.dirname(__file__), 'd8_bootstrap.js'))
29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_PATH_UTILS_JS_DIR = os.path.abspath(
31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    os.path.join(os.path.dirname(__file__), 'path_utils.js'))
32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_HTML_TO_JS_GENERATOR_JS_DIR = os.path.abspath(
34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    os.path.join(os.path.dirname(__file__), 'html_to_js_generator.js'))
35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_BOOTSTRAP_JS_CONTENT = None
38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef _ValidateSourcePaths(source_paths):
41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if source_paths is None:
42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return
43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  for x in source_paths:
44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    assert os.path.exists(x)
45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    assert os.path.isdir(x)
46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    assert os.path.isabs(x)
47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef _GetBootStrapJsContent(source_paths):
50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  global _BOOTSTRAP_JS_CONTENT
51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if not _BOOTSTRAP_JS_CONTENT:
52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    with open(_BOOTSTRAP_JS_DIR, 'r') as f:
53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      _BOOTSTRAP_JS_CONTENT = f.read()
54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  bsc = _BOOTSTRAP_JS_CONTENT
56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  source_path_string = json.dumps(source_paths)
58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  bsc = bsc.replace('<%source_paths%>', source_path_string)
59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  bsc = bsc.replace('<%current_working_directory%>', os.getcwd())
60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  bsc = bsc.replace('<%path_utils_js_path%>', _PATH_UTILS_JS_DIR)
61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  bsc = bsc.replace('<%html_to_js_generator_js_path%>',
62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    _HTML_TO_JS_GENERATOR_JS_DIR)
63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  bsc = bsc.replace('<%js_parser_path%>', _JS_PARSER_DIR)
64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  return bsc
65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef _IsValidJsOrHTMLFile(parser, js_file_arg):
68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if not os.path.exists(js_file_arg):
69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    parser.error('The file %s does not exist' % js_file_arg)
70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  _, extension = os.path.splitext(js_file_arg)
71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if extension not in ('.js', '.html'):
72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    parser.error('Input must be a JavaScript or HTML file')
73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  return js_file_arg
74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef _GetD8BinaryPathForPlatform():
77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if platform.system() == 'Linux' and platform.machine() == 'x86_64':
78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return os.path.join(_V8_DIR, 'linux', 'x86_64', 'd8')
79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  elif platform.system() == 'Darwin' and platform.machine() == 'x86_64':
80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return os.path.join(_V8_DIR, 'mac', 'x86_64', 'd8')
81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  else:
82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    raise NotImplementedError(
83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'd8 binary for this platform and architecture is not yet supported')
84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass RunResult(object):
87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  def __init__(self, returncode, stdout):
88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    self.returncode = returncode
89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    self.stdout = stdout
90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef ExecuteFile(file_path, source_paths=None, js_args=None,
93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                stdout=subprocess.PIPE, stdin=subprocess.PIPE):
94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  """Execute JavaScript program in |file_path|.
95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  Args:
97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    file_path: string file_path that contains path the .js or .html file to be
98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      executed.
99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    source_paths: the list of absolute paths containing code. All the imports
100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    js_args: a list of string arguments to sent to the JS program.
101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  Args stdout & stdin are the same as _RunFileWithD8.
103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  Returns:
105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     The string output from running the JS program.
106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  """
107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  res = RunFile(file_path, source_paths, js_args, stdout, stdin)
108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  return res.stdout
109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef RunFile(file_path, source_paths=None, js_args=None, stdout=subprocess.PIPE,
112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            stdin=subprocess.PIPE):
113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  """Runs JavaScript program in |file_path|.
114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  Args are same as ExecuteFile.
116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  Returns:
118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     A RunResult containing the program's output.
119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  """
120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  assert os.path.isfile(file_path)
121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  _ValidateSourcePaths(source_paths)
122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  _, extension = os.path.splitext(file_path)
124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if not extension in ('.html', '.js'):
125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    raise ValueError('Can only execute .js or .html file. File %s has '
126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                     'unsupported file type: %s' % (file_path, extension))
127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if source_paths is None:
128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    source_paths = [os.path.dirname(file_path)]
129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  abs_file_path = os.path.abspath(file_path)
131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  try:
133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    temp_dir = tempfile.mkdtemp()
134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    temp_boostrap_file = os.path.join(temp_dir, '_tmp_boostrap.js')
135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    with open(temp_boostrap_file, 'w') as f:
136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      f.write(_GetBootStrapJsContent(source_paths))
137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      if extension == '.html':
138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        f.write('\nloadHTMLFile("%s");' % abs_file_path)
139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      else:
140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        f.write('\nloadFile("%s");' % abs_file_path)
141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return _RunFileWithD8(temp_boostrap_file, js_args, stdout, stdin)
142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  finally:
143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    shutil.rmtree(temp_dir)
144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef ExcecuteJsString(js_string, source_paths=None, js_args=None,
147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                     original_file_name=None, stdout=subprocess.PIPE,
148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                     stdin=subprocess.PIPE):
149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  res = RunJsString(js_string, source_paths, js_args, original_file_name,
150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    stdout, stdin)
151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  return res.stdout
152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef RunJsString(js_string, source_paths=None, js_args=None,
155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                original_file_name=None, stdout=subprocess.PIPE,
156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                stdin=subprocess.PIPE):
157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  _ValidateSourcePaths(source_paths)
158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  try:
160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    temp_dir = tempfile.mkdtemp()
161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if original_file_name:
162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      name = os.path.basename(original_file_name)
163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      name, _ = os.path.splitext(name)
164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      temp_file = os.path.join(temp_dir, '%s.js' % name)
165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      temp_file = os.path.join(temp_dir, 'temp_program.js')
167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    with open(temp_file, 'w') as f:
168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      f.write(js_string)
169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return RunFile(temp_file, source_paths, js_args, stdout, stdin)
170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  finally:
171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    shutil.rmtree(temp_dir)
172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef _RunFileWithD8(js_file_path, js_args, stdout, stdin):
175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  """ Execute the js_files with v8 engine and return the output of the program.
176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  Args:
178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    js_file_path: the string path of the js file to be run.
179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    js_args: a list of arguments to passed to the |js_file_path| program.
180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    stdout: where to pipe the stdout of the executed program to. If
181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      subprocess.PIPE is used, stdout will be returned in RunResult.out.
182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      Otherwise RunResult.out is None
183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    stdin: specify the executed program's input.
184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  """
185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  args = [_GetD8BinaryPathForPlatform()]
186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  args.append(os.path.abspath(js_file_path))
187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  full_js_args = [args[0]]
188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if js_args:
189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    full_js_args += js_args
190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  args += ['--js_arguments'] + full_js_args
192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  # Set stderr=None since d8 doesn't write into stderr anyway.
193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  sp = subprocess.Popen(args, stdout=stdout, stderr=None, stdin=stdin)
194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  out, _ = sp.communicate()
195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  # d8 uses returncode 1 to indicate an uncaught exception, but
197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  # _RunFileWithD8 needs to distingiush between that and quit(1).
198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  #
199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  # To fix this, d8_bootstrap.js monkeypatches D8's quit function to
200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  # adds 1 to an intentioned nonzero quit. So, now, we have to undo this
201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  # logic here in order to raise/return the right thing.
202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  returncode = sp.returncode
203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  if returncode == 0:
204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return RunResult(0, out)
205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  elif returncode == 1:
206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if out:
207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      raise RuntimeError(
208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'Exception raised when executing %s:\n%s' % (js_file_path, out))
209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      raise RuntimeError(
211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'Exception raised when executing %s. '
212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        '(Error stack is dumped into stdout)' % js_file_path)
213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  else:
214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return RunResult(returncode - 1, out)
215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef main():
218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  parser = argparse.ArgumentParser(
219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      description='Run JavaScript file with v8 engine')
220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  parser.add_argument('file_name', help='input file', metavar='FILE',
221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                      type=lambda f: _IsValidJsOrHTMLFile(parser, f))
222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  parser.add_argument('--js_args', help='arguments for the js program',
223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                      nargs='+')
224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  parser.add_argument('--source_paths', help='search path for the js program',
225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                      nargs='+', type=str)
226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  args = parser.parse_args()
228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  args.source_paths = [os.path.abspath(x) for x in args.source_paths]
230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  res = RunFile(args.file_name, source_paths=args.source_paths,
231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                js_args=args.js_args, stdout=sys.stdout, stdin=sys.stdin)
232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  return res.returncode
233