1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 """This module contains the Module class and other classes for resources.
6 The Module class represents a module in the trace viewer system. A module has
7 a name, and may require a variety of other resources, such as stylesheets,
8 template objects, raw javascript, or other modules.
10 Other resources include HTML templates, raw javascript files, and stylesheets.
16 from tvcm import module
17 from tvcm import strip_js_comments
19 class JSModule(module.Module):
21 stripped_text = strip_js_comments.strip_js_comments(self.contents)
22 if self.name != 'tvcm':
23 if not IsJSModule(stripped_text):
24 raise module.DepsException('%s is not a JS Module' % self.name)
25 ValidateUsesStrictMode(self.name, stripped_text)
26 if self.name.endswith('_test'):
27 ValidateTestSuiteDefinition(self.name, stripped_text)
28 self.dependency_metadata = Parse(self.name, stripped_text)
30 def IsJSModule(text, text_is_stripped=True):
34 stripped_text = strip_js_comments.strip_js_comments(text)
35 if re.search("""tvcm\s*\.\s*exportTo""",
36 stripped_text, re.DOTALL):
39 if re.search("""tvcm\s*\.\s*require""",
40 stripped_text, re.DOTALL):
43 if re.search("""tvcm\s*\.\s*unittest\s*\.\s*testSuite\((["'])(.+?)\\1""",
44 stripped_text, re.DOTALL):
49 def ValidateTestSuiteDefinition(module_name, stripped_text):
53 m_ts = re.search("""tvcm\s*\.\s*unittest\s*\.\s*testSuite\((["'])(.+?)\\1""",
56 # Figure out which was first.
57 matches = [m for m in [m_ts] if m]
58 matches.sort(key=lambda x: x.start())
64 suite_name = m.group(2)
65 if suite_name != module_name:
66 raise Exception(('%s must use the module name in its testSuite ' +
67 'definition instead of %s') % (module_name, suite_name))
72 raise Exception("""Expected js module %s to contain a ' +
73 'tvcm.unittest.testSuite('%s', ...)""" % (
74 module_name, module_name))
76 raise Exception("""Must only have one tvcm.unittest.testSuite('%s', ...)""" % module_name)
79 def ValidateUsesStrictMode(module_name, stripped_text):
80 """Check that the first non-empty line is 'use strict';.
83 stripped_text: Javascript source code with comments stripped out.
86 DepsException: This file doesn't use strict mode.
88 lines = stripped_text.split('\n')
91 if len(line.strip()) == 0:
93 if """'use strict';""" in line.strip():
95 raise module.DepsException('%s must use strict mode' % module_name)
98 def Parse(module_name, stripped_text):
99 """Parses the tvcm.require* lines in the module and returns module.ModuleDependencyMetadata.
102 stripped_text: Javascript source code with comments stripped out.
105 DepsException: The name of a resource was not formatted properly.
107 res = module.ModuleDependencyMetadata()
109 raise Exception("Module.name must be set.")
113 # Search for require statements in the rest of the file.
114 m_r = re.search("""tvcm\s*\.\s*require\((["'])(.+?)\\1\)""",
116 m_s = re.search("""tvcm\s*\.\s*requireStylesheet\((["'])(.+?)\\1\)""",
118 m_t = re.search("""tvcm\s*\.\s*requireTemplate\((["'])(.+?)\\1\)""",
120 m_irs = re.search("""tvcm\s*\.\s*requireRawScript\((["'])(.+?)\\1\)""",
122 matches = [m for m in [m_r, m_s, m_t, m_irs] if m]
124 # Figure out which was first.
125 matches.sort(key=lambda x: x.start())
132 dependent_module_name = m.group(2)
133 if '/' in dependent_module_name:
134 raise module.DepsException('Slashes are not allowed in module names. '
135 "Use '.' instead: %s" % dependent_module_name)
136 if dependent_module_name.endswith('js'):
137 raise module.DepsException("module names shouldn't end with .js"
138 'The module system will append that for you: %s' %
139 dependent_module_name)
140 res.dependent_module_names.append(dependent_module_name)
142 style_sheet_name = m.group(2)
143 if '/' in style_sheet_name:
144 raise module.DepsException('Slashes are not allowed in style sheet names. '
145 "Use '.' instead: %s" % style_sheet_name)
146 if style_sheet_name.endswith('.css'):
147 raise module.DepsException('Style sheets should not end in .css. '
148 'The module system will append that for you: %s' %
150 res.style_sheet_names.append(style_sheet_name)
152 html_template_name = m.group(2)
153 if '/' in html_template_name:
154 raise module.DepsException('Slashes are not allowed in html template names. '
155 "Use '.' instead: %s" % html_template_name)
156 if html_template_name.endswith('.html'):
157 raise module.DepsException(
158 'HTML templates resource names should not include extension. '
159 'The module system will append that for you.' %
161 res.html_template_names.append(html_template_name)
164 res.dependent_raw_script_relative_paths.append(name)
166 rest = rest[m.end():]