[GTK] Make script dialogs modal to the current web view only
[WebKit-https.git] / Source / JavaScriptCore / Scripts / wkbuiltins / builtins_generator.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2014, 2015 Apple Inc. All rights reserved.
4 # Copyright (c) 2014 University of Washington. All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 # THE POSSIBILITY OF SUCH DAMAGE.
26
27 import logging
28 import os.path
29 import re
30 from string import Template
31 import json
32
33 from builtins_model import BuiltinFunction, BuiltinObject
34 from builtins_templates import BuiltinsGeneratorTemplates as Templates
35
36 log = logging.getLogger('global')
37
38 # These match WK_lcfirst and WK_ucfirst defined in CodeGenerator.pm.
39 def WK_lcfirst(str):
40     str = str[:1].lower() + str[1:]
41     str = str.replace('dOM', 'dom')
42     str = str.replace('uRL', 'url')
43     str = str.replace('jS', 'js')
44     str = str.replace('xML', 'xml')
45     str = str.replace('xSLT', 'xslt')
46     str = str.replace('cSS', 'css')
47     str = str.replace('rTC', 'rtc')
48     return str
49
50 def WK_ucfirst(str):
51     str = str[:1].upper() + str[1:]
52     str = str.replace('Xml', 'XML')
53     str = str.replace('Svg', 'SVG')
54     return str
55
56 class BuiltinsGenerator:
57     def __init__(self, model):
58         self._model = model
59
60     def model(self):
61         return self._model
62
63     # These methods are overridden by subclasses.
64
65     def generate_output(self):
66         pass
67
68     def output_filename(self):
69         pass
70
71
72     # Shared code generation methods.
73     def generate_license(self):
74         raw_license = Template(Templates.LicenseText).substitute(None)
75         copyrights = self._model.copyrights()
76         copyrights.sort()
77
78         license_block = []
79         license_block.append("/*")
80         for copyright in copyrights:
81             license_block.append(" * Copyright (c) %s" % copyright)
82         if len(copyrights) > 0:
83             license_block.append(" * ")
84
85         for line in raw_license.split('\n'):
86             license_block.append(" * " + line)
87
88         license_block.append(" */")
89
90         return '\n'.join(license_block)
91
92     def generate_includes_from_entries(self, entries):
93         includes = set()
94         for entry in entries:
95             (allowed_framework_names, data) = entry
96             (framework_name, header_path) = data
97
98             if self.model().framework.name not in allowed_framework_names:
99                 continue
100             if self.model().framework.name != framework_name:
101                 includes.add("#include <%s/%s>" % (framework_name, os.path.basename(header_path)))
102             else:
103                 includes.add("#include \"%s\"" % os.path.basename(header_path))
104
105         return sorted(list(includes))
106
107     def generate_primary_header_includes(self):
108         name, _ = os.path.splitext(self.output_filename())
109         return '\n'.join([
110             "#include \"config.h\"",
111             "#include \"%s.h\"" % name,
112         ])
113
114     def generate_embedded_code_string_section_for_function(self, function):
115         text = function.function_source
116         # Wrap it in parens to avoid adding to global scope.
117         text = "(function " + text[text.index("("):] + ")"
118         embeddedSourceLength = len(text) + 1  # For extra \n.
119         # Lazy way to escape quotes, I think?
120         textLines = json.dumps(text)[1:-1].split("\\n")
121         # This looks scary because we need the JS source itself to have newlines.
122         embeddedSource = '\n'.join(['    "%s\\n" \\' % line for line in textLines])
123
124         constructAbility = "CannotConstruct"
125         if function.is_constructor:
126             constructAbility = "CanConstruct"
127
128         args = {
129             'codeName': BuiltinsGenerator.mangledNameForFunction(function) + 'Code',
130             'embeddedSource': embeddedSource,
131             'embeddedSourceLength': embeddedSourceLength,
132             'canConstruct': constructAbility,
133             'intrinsic': function.intrinsic
134         }
135
136         lines = []
137         lines.append("const JSC::ConstructAbility s_%(codeName)sConstructAbility = JSC::ConstructAbility::%(canConstruct)s;" % args);
138         lines.append("const int s_%(codeName)sLength = %(embeddedSourceLength)d;" % args);
139         lines.append("static const JSC::Intrinsic s_%(codeName)sIntrinsic = JSC::%(intrinsic)s;" % args);
140         lines.append("const char* s_%(codeName)s =\n%(embeddedSource)s\n;" % args);
141         return '\n'.join(lines)
142
143     # Helper methods.
144
145     @staticmethod
146     def wrap_with_guard(guard, text):
147         if not guard:
148             return text
149         return '\n'.join([
150             '#if %s' % guard,
151             text,
152             '#endif // %s' % guard,
153         ])
154
155     @staticmethod
156     def mangledNameForObject(object):
157         if not isinstance(object, BuiltinObject):
158             raise Exception("Invalid argument passed to mangledNameForObject()")
159
160         def toCamel(match):
161             str = match.group(0)
162             return str[1].upper()
163         return re.sub(r'\.[a-z]', toCamel, object.object_name, flags=re.IGNORECASE)
164
165
166     @staticmethod
167     def mangledNameForFunction(function):
168         if not isinstance(function, BuiltinFunction):
169             raise Exception("Invalid argument passed to mangledNameForFunction()")
170
171         function_name = WK_ucfirst(function.function_name)
172
173         def toCamel(match):
174             str = match.group(0)
175             return str[1].upper()
176         function_name = re.sub(r'\.[a-z]', toCamel, function_name, flags=re.IGNORECASE)
177         if function.is_constructor:
178             function_name = function_name + "Constructor"
179
180         object_name = BuiltinsGenerator.mangledNameForObject(function.object)
181         return WK_lcfirst(object_name + function_name)