Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/tools/feature_matrix.py
4128 views
1
# Copyright 2022 The Emscripten Authors. All rights reserved.
2
# Emscripten is available under two separate licenses, the MIT license and the
3
# University of Illinois/NCSA Open Source License. Both these licenses can be
4
# found in the LICENSE file.
5
6
"""Utilities for mapping browser versions to webassembly features."""
7
8
import logging
9
from enum import IntEnum, auto
10
11
from .settings import settings, user_settings
12
from . import diagnostics
13
14
logger = logging.getLogger('feature_matrix')
15
16
UNSUPPORTED = 0x7FFFFFFF
17
18
# Oldest support browser versions.
19
# Emscripten unconditionally requires support for:
20
# - DedicatedWorkerGlobalScope.name parameter for multithreading support, which
21
# landed first in Chrome 70, Firefox 55 and Safari 12.2.
22
23
# N.b. when modifying these values, update comments in src/settings.js on
24
# MIN_x_VERSION fields to match accordingly.
25
OLDEST_SUPPORTED_CHROME = 70 # Released on 2018-10-16
26
OLDEST_SUPPORTED_FIREFOX = 55 # Released on 2017-08-08
27
OLDEST_SUPPORTED_SAFARI = 120200 # Released on 2019-03-25
28
# 10.19.0 is the oldest version of node that we do any testing with.
29
# Keep this in sync with the test-node-compat in .circleci/config.yml.
30
OLDEST_SUPPORTED_NODE = 101900
31
32
33
class Feature(IntEnum):
34
NON_TRAPPING_FPTOINT = auto()
35
SIGN_EXT = auto()
36
BULK_MEMORY = auto()
37
MUTABLE_GLOBALS = auto()
38
JS_BIGINT_INTEGRATION = auto()
39
THREADS = auto()
40
GLOBALTHIS = auto()
41
PROMISE_ANY = auto()
42
MEMORY64 = auto()
43
44
45
default_features = {Feature.SIGN_EXT, Feature.MUTABLE_GLOBALS}
46
disable_override_features = set()
47
enable_override_features = set()
48
49
min_browser_versions = {
50
Feature.NON_TRAPPING_FPTOINT: {
51
'chrome': 75,
52
'firefox': 65,
53
'safari': 150000,
54
'node': 130000,
55
},
56
Feature.SIGN_EXT: {
57
'chrome': 74,
58
'firefox': 62,
59
'safari': 140100,
60
'node': 120000,
61
},
62
Feature.BULK_MEMORY: {
63
'chrome': 75,
64
'firefox': 79,
65
'safari': 150000,
66
'node': 130000,
67
},
68
Feature.MUTABLE_GLOBALS: {
69
'chrome': 74,
70
'firefox': 61,
71
'safari': 120000,
72
'node': 120000,
73
},
74
Feature.JS_BIGINT_INTEGRATION: {
75
'chrome': 67,
76
'firefox': 68,
77
'safari': 150000,
78
'node': 130000,
79
},
80
Feature.THREADS: {
81
'chrome': 74,
82
'firefox': 79,
83
'safari': 140100,
84
'node': 160400,
85
},
86
Feature.GLOBALTHIS: {
87
'chrome': 71,
88
'firefox': 65,
89
'safari': 120100,
90
'node': 120000,
91
},
92
Feature.PROMISE_ANY: {
93
'chrome': 85,
94
'firefox': 79,
95
'safari': 140000,
96
'node': 150000,
97
},
98
Feature.MEMORY64: {
99
'chrome': 128,
100
'firefox': 129,
101
'safari': UNSUPPORTED,
102
'node': 230000,
103
},
104
}
105
106
107
def caniuse(feature):
108
if feature in disable_override_features:
109
return False
110
if feature in enable_override_features:
111
return True
112
113
min_versions = min_browser_versions[feature]
114
115
def report_missing(setting_name):
116
setting_value = getattr(settings, setting_name)
117
logger.debug(f'cannot use {feature.name} because {setting_name} is too old: {setting_value}')
118
119
if settings.MIN_CHROME_VERSION < min_versions['chrome']:
120
report_missing('MIN_CHROME_VERSION')
121
return False
122
if settings.MIN_FIREFOX_VERSION < min_versions['firefox']:
123
report_missing('MIN_FIREFOX_VERSION')
124
return False
125
if settings.MIN_SAFARI_VERSION < min_versions['safari']:
126
report_missing('MIN_SAFARI_VERSION')
127
return False
128
if 'node' in min_versions and settings.MIN_NODE_VERSION < min_versions['node']:
129
report_missing('MIN_NODE_VERSION')
130
return False
131
return True
132
133
134
def enable_feature(feature, reason, override=False):
135
"""Updates default settings for browser versions such that the given
136
feature is available everywhere.
137
"""
138
if override:
139
enable_override_features.add(feature)
140
for name, min_version in min_browser_versions[feature].items():
141
name = f'MIN_{name.upper()}_VERSION'
142
if settings[name] < min_version:
143
if name in user_settings:
144
# If the user explicitly chose an older version we issue a warning.
145
if name == 'MIN_SAFARI_VERSION' and reason == 'pthreads':
146
# But as a special case, don't warn when forcing on bulk memory on Safari.
147
# This is because Safari implemented part of bulk memory along with threads in 14.1,
148
# but not all of it. So bulk-mem is listed as supported in 15.0. So we want to
149
# continue enabling bulk memory via pthreads without a warning in 14.1, but without
150
# enabling other features requiring 15.0.
151
continue
152
diagnostics.warning(
153
'compatibility',
154
f'{name}={user_settings[name]} is not compatible with {reason} '
155
f'({min_version} or above required)')
156
else:
157
# If no conflict, bump the minimum version to accommodate the feature.
158
setattr(settings, name, min_version)
159
160
161
def disable_feature(feature):
162
"""Allow the user to disable a feature that would otherwise be on by default.
163
"""
164
disable_override_features.add(feature)
165
166
167
# apply minimum browser version defaults based on user settings. if
168
# a user requests a feature that we know is only supported in browsers
169
# from a specific version and above, we can assume that browser version.
170
def apply_min_browser_versions():
171
if settings.WASM_BIGINT and 'WASM_BIGINT' in user_settings:
172
# WASM_BIGINT is enabled by default, don't use it to enable other features
173
# unless the user explicitly enabled it.
174
enable_feature(Feature.JS_BIGINT_INTEGRATION, 'WASM_BIGINT')
175
if settings.PTHREADS:
176
enable_feature(Feature.THREADS, 'pthreads')
177
enable_feature(Feature.BULK_MEMORY, 'pthreads')
178
elif settings.WASM_WORKERS or settings.SHARED_MEMORY:
179
enable_feature(Feature.BULK_MEMORY, 'shared-mem')
180
if settings.AUDIO_WORKLET:
181
enable_feature(Feature.GLOBALTHIS, 'AUDIO_WORKLET')
182
if settings.MEMORY64 == 1:
183
enable_feature(Feature.MEMORY64, 'MEMORY64')
184
185