summaryrefslogtreecommitdiff
blob: ea0626fadadddd05f99ddd66ab8e856143ded554 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
https://bugs.gentoo.org/826762
https://bugzilla.mozilla.org/show_bug.cgi?id=1665675
https://phabricator.services.mozilla.com/D90627
--- a/libraries/source/spidermonkey/patch.sh
+++ b/libraries/source/spidermonkey/patch.sh
@@ -51,5 +51,7 @@ then
     # https://svnweb.freebsd.org/ports/head/lang/spidermonkey78/files/patch-third__party_rust_cc_.cargo-checksum.json?view=log
     patch -p1 < ../FixFreeBSDCargoChecksum.diff
     # https://svnweb.freebsd.org/ports/head/lang/spidermonkey78/files/patch-third__party_rust_cc_src_lib.rs?view=log
     patch -p1 < ../FixFreeBSDRustThirdPartyOSDetection.diff
 fi
+
+patch -p1 < ../FixSysconfigImport.diff
--- a/libraries/source/spidermonkey/FixSysconfigImport.diff
+++ b/libraries/source/spidermonkey/FixSysconfigImport.diff
@@ -0,0 +1,171 @@
+diff --git a/python/mozbuild/mozbuild/configure/__init__.py b/python/mozbuild/mozbuild/configure/__init__.py
+--- a/python/mozbuild/mozbuild/configure/__init__.py
++++ b/python/mozbuild/mozbuild/configure/__init__.py
+@@ -877,17 +877,56 @@
+ 
+     def _apply_imports(self, func, glob):
+         for _from, _import, _as in self._imports.pop(func, ()):
+-            _from = '%s.' % _from if _from else ''
+-            if _as:
+-                glob[_as] = self._get_one_import('%s%s' % (_from, _import))
++            self._get_one_import(_from, _import, _as, glob)
++
++    def _handle_wrapped_import(self, _from, _import, _as, glob):
++        """Given the name of a module, "import" a mocked package into the glob
++        iff the module is one that we wrap (either for the sandbox or for the
++        purpose of testing). Applies if the wrapped module is exposed by an
++        attribute of `self`.
++
++        For example, if the import statement is `from os import environ`, then
++        this function will set
++        glob['environ'] = self._wrapped_os.environ.
++
++        Iff this function handles the given import, return True.
++        """
++        module = (_from or _import).split('.')[0]
++        attr = '_wrapped_' + module
++        wrapped = getattr(self, attr, None)
++        if wrapped:
++            if _as or _from:
++                obj = self._recursively_get_property(
++                    module, (_from + '.' if _from else '') + _import, wrapped)
++                glob[_as or _import] = obj
+             else:
+-                what = _import.split('.')[0]
+-                glob[what] = self._get_one_import('%s%s' % (_from, what))
++                glob[module] = wrapped
++            return True
++        else:
++            return False
++
++    def _recursively_get_property(self, module, what, wrapped):
++        """Traverse the wrapper object `wrapped` (which represents the module
++        `module`) and return the property represented by `what`, which may be a
++        series of nested attributes.
++
++        For example, if `module` is 'os' and `what` is 'os.path.join',
++        return `wrapped.path.join`.
++        """
++        if what == module:
++            return wrapped
++        assert what.startswith(module + '.')
++        attrs = what[len(module + '.'):].split('.')
++        for attr in attrs:
++            wrapped = getattr(wrapped, attr)
++        return wrapped
+ 
+     @memoized_property
+     def _wrapped_os(self):
+         wrapped_os = {}
+         exec_('from os import *', {}, wrapped_os)
++        # Special case os and os.environ so that os.environ is our copy of
++        # the environment.
+         wrapped_os['environ'] = self._environ
+         return ReadOnlyNamespace(**wrapped_os)
+ 
+@@ -913,57 +952,62 @@
+ 
+         return ReadOnlyNamespace(**wrapped_subprocess)
+ 
+-    def _get_one_import(self, what):
+-        # The special `__sandbox__` module gives access to the sandbox
+-        # instance.
+-        if what == '__sandbox__':
+-            return self
++    @memoized_property
++    def _wrapped_six(self):
++        if six.PY3:
++            return six
++        wrapped_six = {}
++        exec_('from six import *', {}, wrapped_six)
++        wrapped_six_moves = {}
++        exec_('from six.moves import *', {}, wrapped_six_moves)
++        wrapped_six_moves_builtins = {}
++        exec_('from six.moves.builtins import *', {},
++              wrapped_six_moves_builtins)
++
+         # Special case for the open() builtin, because otherwise, using it
+         # fails with "IOError: file() constructor not accessible in
+         # restricted mode". We also make open() look more like python 3's,
+         # decoding to unicode strings unless the mode says otherwise.
+-        if what == '__builtin__.open' or what == 'builtins.open':
+-            if six.PY3:
+-                return open
++        def wrapped_open(name, mode=None, buffering=None):
++            args = (name,)
++            kwargs = {}
++            if buffering is not None:
++                kwargs['buffering'] = buffering
++            if mode is not None:
++                args += (mode,)
++                if 'b' in mode:
++                    return open(*args, **kwargs)
++            kwargs['encoding'] = system_encoding
++            return codecs.open(*args, **kwargs)
++
++        wrapped_six_moves_builtins['open'] = wrapped_open
++        wrapped_six_moves['builtins'] = ReadOnlyNamespace(
++            **wrapped_six_moves_builtins)
++        wrapped_six['moves'] = ReadOnlyNamespace(**wrapped_six_moves)
+ 
+-            def wrapped_open(name, mode=None, buffering=None):
+-                args = (name,)
+-                kwargs = {}
+-                if buffering is not None:
+-                    kwargs['buffering'] = buffering
+-                if mode is not None:
+-                    args += (mode,)
+-                    if 'b' in mode:
+-                        return open(*args, **kwargs)
+-                kwargs['encoding'] = system_encoding
+-                return codecs.open(*args, **kwargs)
+-            return wrapped_open
+-        # Special case os and os.environ so that os.environ is our copy of
+-        # the environment.
+-        if what == 'os.environ':
+-            return self._environ
+-        if what == 'os':
+-            return self._wrapped_os
+-        # And subprocess, so that its functions use our os.environ
+-        if what == 'subprocess':
+-            return self._wrapped_subprocess
+-        if what in ('subprocess.call', 'subprocess.check_call',
+-                    'subprocess.check_output', 'subprocess.Popen'):
+-            return getattr(self._wrapped_subprocess, what[len('subprocess.'):])
++        return ReadOnlyNamespace(**wrapped_six)
++
++    def _get_one_import(self, _from, _import, _as, glob):
++        """Perform the given import, placing the result into the dict glob."""
++        if not _from and _import == '__builtin__':
++            glob[_as or '__builtin__'] = __builtin__
++            return
++        if _from == '__builtin__':
++            _from = 'six.moves.builtins'
++        # The special `__sandbox__` module gives access to the sandbox
++        # instance.
++        if not _from and _import == '__sandbox__':
++            glob[_as or _import] = self
++            return
++        if self._handle_wrapped_import(_from, _import, _as, glob):
++            return
++        # If we've gotten this far, we should just do a normal import.
+         # Until this proves to be a performance problem, just construct an
+         # import statement and execute it.
+-        import_line = ''
+-        if '.' in what:
+-            _from, what = what.rsplit('.', 1)
+-            if _from == '__builtin__' or _from.startswith('__builtin__.'):
+-                _from = _from.replace('__builtin__', 'six.moves.builtins')
+-            import_line += 'from %s ' % _from
+-        if what == '__builtin__':
+-            what = 'six.moves.builtins'
+-        import_line += 'import %s as imported' % what
+-        glob = {}
++        import_line = '%simport %s%s' % (
++            ('from %s ' % _from) if _from else '', _import,
++            (' as %s' % _as) if _as else '')
+         exec_(import_line, {}, glob)
+-        return glob['imported']
+ 
+     def _resolve_and_set(self, data, name, value, when=None):
+         # Don't set anything when --help was on the command line