shaka-player 3.3.7 → 3.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/.github/workflows/build-and-test.yaml +67 -15
  2. package/.github/workflows/compute-incremental-coverage.py +251 -0
  3. package/.github/workflows/report-incremental-coverage.yaml +39 -0
  4. package/.github/workflows/selenium-lab-tests.yaml +179 -31
  5. package/AUTHORS +1 -0
  6. package/CHANGELOG.md +36 -0
  7. package/CONTRIBUTORS +3 -0
  8. package/README.md +20 -6
  9. package/demo/index.html +0 -2
  10. package/dist/controls.css +2 -2
  11. package/dist/controls.css.map +1 -1
  12. package/dist/deps.js +2 -2
  13. package/dist/locales.js +31 -31
  14. package/dist/shaka-player.compiled.d.ts +12 -1
  15. package/dist/shaka-player.compiled.debug.d.ts +12 -1
  16. package/dist/shaka-player.compiled.debug.externs.js +49 -38
  17. package/dist/shaka-player.compiled.debug.js +116 -105
  18. package/dist/shaka-player.compiled.debug.map +4 -4
  19. package/dist/shaka-player.compiled.externs.js +49 -38
  20. package/dist/shaka-player.compiled.js +778 -773
  21. package/dist/shaka-player.compiled.map +4 -4
  22. package/dist/shaka-player.ui.d.ts +12 -1
  23. package/dist/shaka-player.ui.debug.d.ts +12 -1
  24. package/dist/shaka-player.ui.debug.externs.js +49 -38
  25. package/dist/shaka-player.ui.debug.js +131 -120
  26. package/dist/shaka-player.ui.debug.map +4 -4
  27. package/dist/shaka-player.ui.externs.js +49 -38
  28. package/dist/shaka-player.ui.js +905 -901
  29. package/dist/shaka-player.ui.map +4 -4
  30. package/docs/tutorials/welcome.md +6 -3
  31. package/karma.conf.js +3 -11
  32. package/lib/ads/client_side_ad_manager.js +1 -1
  33. package/lib/dash/dash_parser.js +5 -0
  34. package/lib/hls/hls_parser.js +6 -2
  35. package/lib/media/drm_engine.js +1 -1
  36. package/lib/media/presentation_timeline.js +24 -1
  37. package/lib/media/streaming_engine.js +1 -0
  38. package/lib/player.js +7 -6
  39. package/lib/polyfill/media_capabilities.js +3 -0
  40. package/lib/polyfill/videoplaybackquality.js +3 -1
  41. package/lib/text/cue.js +0 -5
  42. package/lib/text/simple_text_displayer.js +21 -9
  43. package/lib/text/ui_text_displayer.js +91 -19
  44. package/lib/util/buffer_utils.js +3 -0
  45. package/lib/util/object_utils.js +1 -0
  46. package/lib/util/platform.js +41 -1
  47. package/lib/util/stream_utils.js +23 -3
  48. package/lib/util/string_utils.js +102 -13
  49. package/maintained-branches.md +15 -0
  50. package/package.json +6 -5
  51. package/test/player_src_equals_integration.js +2 -0
  52. package/test/test/assets/small.mp4 +0 -0
  53. package/test/text/simple_text_displayer_unit.js +27 -0
  54. package/test/text/ui_text_displayer_unit.js +65 -0
  55. package/test/util/string_utils_unit.js +46 -8
  56. package/ui/less/ad_controls.less +4 -0
  57. package/ui/text_selection.js +2 -2
  58. package/app-engine/README.md +0 -9
  59. package/app-engine/demo-version-index/README.md +0 -14
  60. package/app-engine/demo-version-index/app.yaml +0 -2
  61. package/app-engine/demo-version-index/main.py +0 -162
  62. package/app-engine/demo-version-index/requirements.txt +0 -6
  63. package/app-engine/demo-version-index/templates/index.html +0 -114
  64. package/app-engine/shaka-player-demo/README.md +0 -18
  65. package/app-engine/shaka-player-demo/app.yaml +0 -61
  66. package/app-engine/shaka-player-demo/main.py +0 -95
  67. package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
  68. package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
  69. package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
  70. package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
  71. package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
  72. package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
  73. package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
  74. package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
  75. package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
  76. package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
  77. package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
  78. package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
  79. package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
  80. package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
  81. package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
  82. package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
  83. package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
  84. package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
  85. package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
  86. package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
  87. package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
  88. package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
  89. package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
  90. package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
  91. package/app-engine/shaka-player-demo/posters/sources.txt +0 -46
  92. package/app-engine/shaka-player-demo/posters/standard.png +0 -0
  93. package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
  94. package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
  95. package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
  96. package/app-engine/shaka-player-demo/posters.py +0 -110
  97. package/app-engine/shaka-player-demo/requirements.txt +0 -5
  98. package/app-engine/shaka-player-demo/time.txt +0 -1
  99. package/build/README.md +0 -127
  100. package/build/__init__.py +0 -0
  101. package/build/all.py +0 -150
  102. package/build/apps.py +0 -186
  103. package/build/build.py +0 -392
  104. package/build/check.py +0 -354
  105. package/build/checkversion.py +0 -84
  106. package/build/compiler.py +0 -513
  107. package/build/conformance.textproto +0 -335
  108. package/build/docker/Dockerfile +0 -20
  109. package/build/docker/docker-compose.yml +0 -10
  110. package/build/docs.py +0 -54
  111. package/build/eslint-plugin-shaka-rules/arg-comment-spacing.js +0 -72
  112. package/build/eslint-plugin-shaka-rules/index.js +0 -24
  113. package/build/eslint-plugin-shaka-rules/package.json +0 -7
  114. package/build/eslint-plugin-shaka-rules/private.js +0 -109
  115. package/build/gendeps.py +0 -71
  116. package/build/generateExterns.js +0 -867
  117. package/build/generateLocalizations.py +0 -262
  118. package/build/generateTsDefs.py +0 -137
  119. package/build/install-linux-prereqs.sh +0 -136
  120. package/build/license-header +0 -5
  121. package/build/misspellings.txt +0 -38
  122. package/build/pixelsChanged.js +0 -35
  123. package/build/shaka-lab.yaml +0 -163
  124. package/build/shakaBuildHelpers.py +0 -356
  125. package/build/stats.py +0 -816
  126. package/build/subprocessWindowsPatch.py +0 -103
  127. package/build/test.py +0 -541
  128. package/build/types/ads +0 -8
  129. package/build/types/cast +0 -6
  130. package/build/types/cea +0 -13
  131. package/build/types/complete +0 -9
  132. package/build/types/core +0 -108
  133. package/build/types/dash +0 -8
  134. package/build/types/hls +0 -9
  135. package/build/types/manifests +0 -5
  136. package/build/types/networking +0 -6
  137. package/build/types/offline +0 -22
  138. package/build/types/polyfill +0 -21
  139. package/build/types/text +0 -11
  140. package/build/types/ui +0 -39
  141. package/build/updateScreenshots.py +0 -85
  142. package/build/wrapper.template.js +0 -52
@@ -1,163 +0,0 @@
1
- # Selenium grid config for the Shaka lab. This is the source of truth for the
2
- # browsers and devices in the Shaka lab at Google.
3
-
4
- # For syntax and general information, see docs/selenium-grid-config.md
5
-
6
-
7
- # A set of variables to contain repeated configurations which can then be
8
- # referenced below. The syntax for the variable is "name: &name", which
9
- # generates an "anchor" with the given name. Later, you can inject the
10
- # contents of the variable with "*name".
11
- vars:
12
- firefox_config: &firefox_config
13
- moz:firefoxOptions:
14
- # Override Firefox default preferences in the temporary profile created
15
- # for each test run.
16
- prefs:
17
- # Overrides Selenium's explicit default setting, to allow Firefox to
18
- # install the Widevine CDM on demand.
19
- media.gmp-manager.updateEnabled: true
20
- # Overrides Firefox's Linux-specific default setting to disable DRM.
21
- media.eme.enabled: true
22
-
23
- minimum_chrome_args: &minimum_chrome_args
24
- # On Chrome m59+ we can test EME on platforms with pop-up prompts, such as
25
- # Android and ChromeOS. Note that this flag does not take a port number
26
- # (domain vs origin).
27
- # This flag requires setting --user-data-dir as well, however, webdriver
28
- # already takes care of that for us (except on Android).
29
- - "--unsafely-allow-protected-media-identifier-for-domain=karma.shakalab.rocks"
30
- # Normally, Chrome disallows autoplaying videos in many cases. Enable it
31
- # for testing.
32
- - "--autoplay-policy=no-user-gesture-required"
33
-
34
- minimum_chrome_android_args: &minimum_chrome_android_args
35
- # There is no way in YAML to natively merge arrays, so we start by
36
- # duplicating the flags from minimum_chrome_args above.
37
- - "--unsafely-allow-protected-media-identifier-for-domain=karma.shakalab.rocks"
38
- - "--autoplay-policy=no-user-gesture-required"
39
- # On Android we must set --user-data-dir. WebDriver does not do it for
40
- # us as it does on other platforms. Without --user-data-dir,
41
- # --unsafely-allow... does not work.
42
- - "--user-data-dir=/data/data/com.android.chrome/cache"
43
-
44
- minimum_chromeos_args: &minimum_chromeos_args
45
- # There is no way in YAML to natively merge arrays, so we start by
46
- # duplicating the flags from minimum_chrome_args above.
47
- - "--unsafely-allow-protected-media-identifier-for-domain=karma.shakalab.rocks"
48
- - "--autoplay-policy=no-user-gesture-required"
49
- # Allow remote attestation even though the device may be in dev mode. This
50
- # is critical for testing involving L1 content licenses.
51
- - "--allow-ra-in-dev-mode"
52
-
53
- chrome_config: &chrome_config
54
- goog:chromeOptions:
55
- args: *minimum_chrome_args
56
-
57
- # Instruct chromedriver not to disable component updater. The
58
- # component updater must run in order for the Widevine CDM to be
59
- # available when using a new user-data-dir.
60
- # TODO(http://crbug.com/613581): Remove once Chrome bug is fixed.
61
- excludeSwitches:
62
- - "disable-component-update"
63
-
64
- chrome_android_config: &chrome_android_config
65
- goog:chromeOptions:
66
- args: *minimum_chrome_android_args
67
-
68
- # Once the new session request reaches chromedriver, it will take
69
- # the androidPackage option as a request to start Chrome through
70
- # adb on the tethered device.
71
- androidPackage: com.android.chrome
72
-
73
- chromeos_config: &chromeos_config
74
- # Pass these client-specified arguments through generic-webdriver-server.
75
- # This array will be appended after "--" instead of being set through one
76
- # specific flag. For example, with ["--foo", "--bar=baz"] in the args,
77
- # this would generate a command like:
78
- # chromeos-webdriver-server.js -- --foo --bar=baz
79
- # Those parameters will be passed on to Chrome instead of used by the
80
- # WebDriver server.
81
- generic:args: *minimum_chromeos_args
82
-
83
-
84
- ChromeMac:
85
- browser: chrome
86
- os: Mac
87
- extra_config: *chrome_config
88
-
89
- FirefoxMac:
90
- browser: firefox
91
- os: Mac
92
- extra_config: *firefox_config
93
-
94
- Safari:
95
- browser: safari
96
- os: Mac
97
-
98
- SafariTP:
99
- # TODO(b/152646297): Safari TP not launching as of Safari 15.4
100
- disabled: true
101
- browser: safari
102
- os: Mac
103
- extra_config:
104
- safari.options:
105
- technologyPreview: true
106
-
107
- ChromeWindows:
108
- browser: chrome
109
- os: Windows
110
- extra_config: *chrome_config
111
-
112
- FirefoxWindows:
113
- browser: firefox
114
- os: Windows
115
- extra_config: *firefox_config
116
-
117
- IE11:
118
- # IE11 support has been removed from the latest release branch.
119
- disabled: true
120
- browser: internet explorer
121
- os: Windows
122
- extra_config:
123
- se:ieOptions:
124
- # The zoom setting must be checked, or screenshot tests will be way off!
125
- ignoreZoomSetting: false
126
- ignoreProtectedModeSettings: true
127
-
128
- Edge:
129
- browser: msedge
130
- os: Windows
131
-
132
- ChromeLinux:
133
- browser: chrome
134
- os: Linux
135
- extra_config: *chrome_config
136
-
137
- FirefoxLinux:
138
- browser: firefox
139
- os: Linux
140
- extra_config: *firefox_config
141
-
142
- ChromeAndroid:
143
- browser: chrome
144
- os: Android
145
- extra_config: *chrome_android_config
146
-
147
- Chromecast:
148
- browser: chromecast
149
-
150
- Chromebook:
151
- # TODO(b/145916766): Persistent license tests failing
152
- disabled: true
153
- browser: chromeos
154
- version: Pixelbook
155
- extra_config: *chromeos_config
156
-
157
- Tizen:
158
- # TODO(joeyparrish): Get Tizen TV mounted in the lab and connected
159
- disabled: true
160
- browser: tizen
161
-
162
- XboxOne:
163
- browser: xboxone
@@ -1,356 +0,0 @@
1
- # Copyright 2016 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- """Contains helper functions used in the build scripts.
16
-
17
- This uses two environment variables to help with debugging the scripts:
18
-
19
- PRINT_ARGUMENTS - If set, will print any arguments to subprocess.
20
- RAISE_INTERRUPT - Will raise keyboard interrupts rather than swallowing them.
21
- """
22
-
23
- from __future__ import print_function
24
-
25
- import errno
26
- import json
27
- import logging
28
- import os
29
- import platform
30
- import re
31
- import subprocess
32
- import sys
33
- import time
34
-
35
- import subprocessWindowsPatch
36
-
37
-
38
- # Python 3 no longer has a separate unicode type. For type-checking done in
39
- # get_node_binary, create an alias to the str type.
40
- if sys.version_info[0] == 3:
41
- unicode = str
42
-
43
-
44
- def _node_modules_last_update_path():
45
- return os.path.join(get_source_base(), 'node_modules', '.last_update')
46
-
47
-
48
- def _modules_need_update():
49
- try:
50
- last_update = os.path.getmtime(_node_modules_last_update_path())
51
- if last_update > time.time():
52
- # Update time in the future! Something is wrong, so update.
53
- return True
54
-
55
- package_json_path = os.path.join(get_source_base(), 'package.json')
56
- last_json_change = os.path.getmtime(package_json_path)
57
- if last_json_change >= last_update:
58
- # The json file has changed, so update.
59
- return True
60
- except:
61
- # No such file, so we should update.
62
- return True
63
-
64
- return False
65
-
66
- def get_source_base():
67
- """Returns the absolute path to the source code base."""
68
- return os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
69
-
70
-
71
- def is_linux():
72
- """Determines if the system is Linux."""
73
- return platform.uname()[0] == 'Linux'
74
-
75
-
76
- def is_darwin():
77
- """Determines if the system is a Mac."""
78
- return platform.uname()[0] == 'Darwin'
79
-
80
-
81
- def is_windows():
82
- """Determines if the system is native Windows (i.e. not Cygwin)."""
83
- return platform.uname()[0] == 'Windows'
84
-
85
-
86
- def is_cygwin():
87
- """Determines if the system is Cygwin (i.e. not native Windows)."""
88
- return 'CYGWIN' in platform.uname()[0]
89
-
90
-
91
- def quote_argument(arg):
92
- """Wraps the given argument in quotes if needed.
93
-
94
- This is so execute_subprocess output can be copied and pasted into a shell.
95
-
96
- Args:
97
- arg: The string to convert.
98
-
99
- Returns:
100
- The quoted argument.
101
- """
102
- if '"' in arg:
103
- assert "'" not in arg
104
- return "'" + arg + "'"
105
- if "'" in arg:
106
- assert '"' not in arg
107
- return '"' + arg + '"'
108
- if ' ' in arg:
109
- return '"' + arg + '"'
110
- return arg
111
-
112
-
113
- def open_file(*args, **kwargs):
114
- """Opens a file with the given mode and options."""
115
- if sys.version_info[0] == 2:
116
- # Python 2 returns byte strings even in text mode, so the encoding doesn't
117
- # matter.
118
- return open(*args, **kwargs)
119
- else:
120
- # Python 3 requires setting an encoding so it reads strings. The default
121
- # is based on the platform, which on Windows, isn't UTF-8.
122
- return open(encoding='utf8', *args, **kwargs)
123
-
124
-
125
- def execute_subprocess(args, **kwargs):
126
- """Executes the given command using subprocess.
127
-
128
- If PRINT_ARGUMENTS environment variable is set, this will first print the
129
- arguments.
130
-
131
- Args:
132
- args: A list of strings for the subprocess to run.
133
- kwargs: Extra keyword arguments to pass to Popen.
134
-
135
- Returns:
136
- The same value as subprocess.Popen.
137
- """
138
- # Windows can't run scripts directly, even if executable. We need to
139
- # explicitly run the interpreter.
140
- if args[0].endswith('.js'):
141
- raise ValueError('Use "node" to run JavaScript scripts')
142
- if args[0].endswith('.py'):
143
- raise ValueError('Use sys.executable to run Python scripts')
144
-
145
- if os.environ.get('PRINT_ARGUMENTS'):
146
- logging.info(' '.join([quote_argument(x) for x in args]))
147
- try:
148
- return subprocess.Popen(args, **kwargs)
149
- except OSError as e:
150
- if e.errno == errno.ENOENT:
151
- logging.error('*** A required dependency is missing: %s', args[0])
152
- # Exit early to avoid showing a confusing stack trace.
153
- sys.exit(1)
154
- raise
155
-
156
-
157
- def execute_get_code(args):
158
- """Calls execute_subprocess and gets return code."""
159
- obj = execute_subprocess(args)
160
- obj.communicate()
161
- return obj.returncode
162
-
163
-
164
- def execute_get_output(args):
165
- """Calls execute_subprocess and get the stdout of the process."""
166
- obj = execute_subprocess(args, stdout=subprocess.PIPE)
167
- # This will block until the process terminates, storing the stdout in a string
168
- stdout = obj.communicate()[0]
169
- if obj.returncode != 0:
170
- raise subprocess.CalledProcessError(obj.returncode, args[0], stdout)
171
- return stdout
172
-
173
-
174
- def cygwin_safe_path(path):
175
- """Converts the given path to a Cygwin path, if needed."""
176
- if is_cygwin():
177
- return execute_get_output(['cygpath', '-w', path]).strip()
178
- else:
179
- return path
180
-
181
-
182
- def git_version():
183
- """Gets the version of the library from git."""
184
- # Check if the shaka-player source base directory has '.git' file.
185
- git_path = os.path.join(get_source_base(), '.git')
186
- if not os.path.exists(git_path):
187
- raise RuntimeError('no .git file is in the shaka-player repository.')
188
- else:
189
- try:
190
- # Check git tags for a version number, noting if the sources are dirty.
191
- cmd_line = ['git', '-C', get_source_base(), 'describe', '--tags', '--dirty']
192
- return execute_get_output(cmd_line).decode('utf8').strip()
193
- except subprocess.CalledProcessError:
194
- raise RuntimeError('Unable to determine library version!')
195
-
196
-
197
- def npm_version(is_dirty=False):
198
- """Gets the version of the library from NPM."""
199
- try:
200
- base = cygwin_safe_path(get_source_base())
201
- cmd_line = ['npm', '--prefix', base, 'ls', 'shaka-player']
202
- text = execute_get_output(cmd_line).decode('utf8')
203
- except subprocess.CalledProcessError as e:
204
- text = e.output.decode('utf8')
205
- match = re.search(r'shaka-player@(.*) ', text)
206
- if match:
207
- return match.group(1) + ('-npm-dirty' if is_dirty else '')
208
- raise RuntimeError('Unable to determine library version!')
209
-
210
-
211
- def calculate_version():
212
- """Returns the version of the library."""
213
- # Fall back to NPM's installed package version, and assume the sources
214
- # are dirty since the build scripts are being run at all after install.
215
- try:
216
- return git_version()
217
- except RuntimeError:
218
- # If there is an error in |git_version|, ignore it and try NPM. If there
219
- # is an error with NPM, propagate the error.
220
- return npm_version(is_dirty=True)
221
-
222
-
223
- def get_closure_base_js_path():
224
- return os.path.join(get_source_base(),
225
- 'node_modules', 'google-closure-library', 'closure', 'goog', 'base.js')
226
-
227
-
228
- def get_all_js_files(*path_components):
229
- """Get all JavaScript file paths recursively from the given path components.
230
-
231
- Args:
232
- *path_components: The components of the path to search. Joining is handling
233
- internally according to os path semantics.
234
- Returns:
235
- An array of absolute paths to all JS files.
236
- """
237
- match = re.compile(r'.*\.js$')
238
- return get_all_files(
239
- os.path.join(get_source_base(), *path_components), match)
240
-
241
-
242
- def get_all_files(dir_path, exp=None):
243
- """Get all file paths recursively within the given path.
244
-
245
- This optionally will filter the output using the given regex.
246
-
247
- Args:
248
- dir_path: The string path to search.
249
- exp: A regex to match, can be None.
250
-
251
- Returns:
252
- An array of absolute paths to all the files.
253
- """
254
- ret = []
255
- for root, _, files in os.walk(dir_path):
256
- for f in files:
257
- if not exp or exp.match(f):
258
- ret.append(os.path.join(root, f))
259
- ret.sort()
260
- return ret
261
-
262
-
263
- def get_node_binary(module_name, bin_name=None):
264
- """Returns an array to be used in the command-line execution of a node binary.
265
-
266
- For example, this may return ['eslint'] (global install)
267
- or ['node', 'path/to/node_modules/eslint/bin/eslint.js'] (local install).
268
-
269
- Arguments:
270
- module_name: A string, the name of the module.
271
- bin_name: An optional string, the name of the binary, which defaults to
272
- module_name if not provided.
273
-
274
- Returns:
275
- An array of strings which form the command-line to call the binary.
276
- """
277
-
278
- if not bin_name:
279
- bin_name = module_name
280
-
281
- # Check local modules first.
282
- base = get_source_base()
283
- path = os.path.join(base, 'node_modules', module_name)
284
- if os.path.isdir(path):
285
- json_path = os.path.join(path, 'package.json')
286
- package_data = json.load(open_file(json_path, 'r'))
287
- bin_data = package_data['bin']
288
-
289
- if type(bin_data) is str or type(bin_data) is unicode:
290
- # There's only one binary here.
291
- bin_rel_path = bin_data
292
- else:
293
- # It's a dictionary, so look up the specific binary we want.
294
- bin_rel_path = bin_data[bin_name]
295
-
296
- bin_path = os.path.join(path, bin_rel_path)
297
- return ['node', bin_path]
298
-
299
- # Not found locally, assume it can be found in os.environ['PATH'].
300
- return [bin_name]
301
-
302
-
303
- class InDir(object):
304
- """A Context Manager that changes directories temporarily and safely."""
305
- def __init__(self, path):
306
- self.new_path = path
307
-
308
- def __enter__(self):
309
- self.old_path = os.getcwd()
310
- os.chdir(self.new_path)
311
-
312
- def __exit__(self, type, value, traceback):
313
- os.chdir(self.old_path)
314
-
315
-
316
- def update_node_modules():
317
- """Updates the node modules using 'npm', if they have not already been
318
- updated recently enough."""
319
- if not _modules_need_update():
320
- return True
321
-
322
- base = cygwin_safe_path(get_source_base())
323
-
324
- # Update the modules.
325
- # Actually change directories instead of using npm --prefix.
326
- # See npm/npm#17027 and shaka-project/shaka-player#776 for more details.
327
- with InDir(base):
328
- # npm ci uses package-lock.json to get a stable, reproducible set of
329
- # packages installed.
330
- execute_get_output(['npm', 'ci'])
331
-
332
- # Update the timestamp of the file that tracks when we last updated.
333
- open(_node_modules_last_update_path(), 'wb').close()
334
- return True
335
-
336
-
337
- def run_main(main):
338
- """Executes the given function with the current command-line arguments.
339
-
340
- This calls exit with the return value. This ignores keyboard interrupts.
341
-
342
- Args:
343
- main: The main function to call.
344
- """
345
- logging.getLogger().setLevel(logging.INFO)
346
- fmt = '[%(levelname)s] %(message)s'
347
- logging.basicConfig(format=fmt)
348
-
349
- try:
350
- sys.exit(main(sys.argv[1:]))
351
- except KeyboardInterrupt:
352
- if os.environ.get('RAISE_INTERRUPT'):
353
- raise
354
- print(file=sys.stderr) # Clear the current line that has ^C on it.
355
- logging.error('Keyboard interrupt')
356
- sys.exit(1)