Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions build/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,33 @@ def check_tests(args):
closure_base_js = shakaBuildHelpers.get_closure_base_js_path()
get = shakaBuildHelpers.get_all_js_files

localizations = compiler.GenerateLocalizations(None)
localizations.generate(args.force)

# Generate a standalone externs file with the shaka namespace typedef, so the
# tests can refer to the whole library namespace in a type-safe way without a
# hand-maintained typedef. We use the complete build's sources (plus the
# generated localizations they depend on) so the typedef covers every
# top-level namespace that the tests might reference. This is done before the
# test and externs files are added below, since those are not part of the
# library namespace.
node_modules_path = os.path.join(base, 'node_modules')
namespace_sources = [f for f in complete_build if node_modules_path not in f]
namespace_sources.append(localizations.output)
namespace_externs = compiler.NamespaceExternGenerator(
namespace_sources, 'shaka-namespace')
if not namespace_externs.generate(args.force):
return False

files = complete_build
files.update(set(
get('externs') +
get('test') +
[closure_base_js]))
files.add(os.path.join(base, 'demo', 'common', 'asset.js'))
files.add(os.path.join(base, 'demo', 'common', 'assets.js'))

localizations = compiler.GenerateLocalizations(None)
localizations.generate(args.force)
files.add(localizations.output)
files.add(namespace_externs.output)

closure_opts = build.common_closure_opts + build.common_closure_defines
closure_opts += build.debug_closure_opts + build.debug_closure_defines
Expand Down
35 changes: 35 additions & 0 deletions build/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,41 @@ def generate(self, force=False):
return True


class NamespaceExternGenerator(object):
"""Generates a standalone externs file with only the shaka namespace typedef.

Unlike ExternGenerator, this does not re-declare the library API, so the
output can be type-checked alongside the uncompiled source (e.g. the tests).
"""

def __init__(self, source_files, output_name):
self.source_files = _canonicalize_source_files(source_files)
self.output = _get_source_path('dist/' + output_name + '.externs.js')

def generate(self, force=False):
"""Generates the shaka namespace typedef for |self.source_files|.

Args:
force: Generate the output even if the inputs have not changed.

Returns:
True on success; False on failure.
"""
if not force and not _must_build(self.output, self.source_files):
return True

extern_generator = _get_source_path('build/generateExterns.js')

cmd_line = ['node', extern_generator, '--namespace-typedef', self.output]
cmd_line += self.source_files

if shakaBuildHelpers.execute_get_code(cmd_line) != 0:
logging.error('Namespace typedef generation failed')
return False

return True


class TsDefGenerator(object):
def __init__(self, source_files, build_name):
self.source_files = _canonicalize_source_files(source_files)
Expand Down
45 changes: 34 additions & 11 deletions build/generateExterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -908,16 +908,22 @@ function generateShakaNamespaceTypedef(names) {
function main(args) {
const inputPaths = [];
let outputPath;
let namespaceTypedefPath;

for (let i = 0; i < args.length; ++i) {
if (args[i] == '--output') {
outputPath = args[i + 1];
++i;
} else if (args[i] == '--namespace-typedef') {
namespaceTypedefPath = args[i + 1];
++i;
} else {
inputPaths.push(args[i]);
}
}
assert(outputPath, 'You must specify output file with --output <EXTERNS>');
assert(outputPath || namespaceTypedefPath,
'You must specify an output file with --output <EXTERNS> and/or ' +
'--namespace-typedef <EXTERNS>');
assert(inputPaths.length, 'You must specify at least one input file.');

// Generate externs for all input paths.
Expand Down Expand Up @@ -978,16 +984,33 @@ function main(args) {
const shakaTypedef = generateShakaNamespaceTypedef(names);

// Output generated externs, with an appropriate header.
fs.writeFileSync(outputPath,
licenseHeader +
'/**\n' +
' * @fileoverview Generated externs. DO NOT EDIT!\n' +
' * @externs\n' +
' * @suppress {constantProperty, duplicate} To prevent compiler\n' +
' * errors with the namespace being declared both here and by\n' +
' * goog.provide in the library.\n' +
' */\n\n' +
namespaceDeclarations.join('') + '\n' + shakaTypedef + externs);
if (outputPath) {
fs.writeFileSync(outputPath,
licenseHeader +
'/**\n' +
' * @fileoverview Generated externs. DO NOT EDIT!\n' +
' * @externs\n' +
' * @suppress {constantProperty, duplicate} To prevent compiler\n' +
' * errors with the namespace being declared both here and by\n' +
' * goog.provide in the library.\n' +
' */\n\n' +
namespaceDeclarations.join('') + '\n' + shakaTypedef + externs);
}

// Output a standalone externs file with only the shaka namespace typedef.
// Unlike the full externs above, this does not re-declare the library API, so
// it can be type-checked alongside the uncompiled source (e.g. in the tests)
// without conflicting with the goog.provide declarations.
if (namespaceTypedefPath) {
fs.writeFileSync(namespaceTypedefPath,
licenseHeader +
'/**\n' +
' * @fileoverview Generated externs for the shaka namespace type.\n' +
' * DO NOT EDIT!\n' +
' * @externs\n' +
' */\n\n' +
shakaTypedef);
}
}


Expand Down
8 changes: 4 additions & 4 deletions test/offline/storage_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1849,14 +1849,14 @@ filterDescribe('Storage', storageSupport, () => {
* @param {string} uri
* @param {number} startTime
* @param {number} endTime
* @param {shakaNamespaceType=} compiledShaka
* @param {shaka=} compiledShaka
* @return {shaka.media.SegmentReference}
*/
function makeReference(uri, startTime, endTime, compiledShaka) {
/** @type {shakaNamespaceType} */
const shaka = compiledShaka || window['shaka'];
/** @type {shaka} */
const shakaNamespace = compiledShaka || window['shaka'];

return new shaka.media.SegmentReference(
return new shakaNamespace.media.SegmentReference(
startTime,
endTime,
/* getUris= */ () => [uri],
Expand Down
40 changes: 2 additions & 38 deletions test/test/util/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,15 @@
* SPDX-License-Identifier: Apache-2.0
*/

/**
* A stand-in type for the "shaka" namespace. Used when loading the compiled
* library or when referencing it in ManifestGenerator or TestScheme.
*
* The new compiler has a "typeof" annotation for classes, but it warns of an
* incomplete type when used on the entire library namespace. So instead, we
* use this type, which maps out parts of the compiled namespace used in
* top-level integration tests.
*
* @typedef {{
* Player: typeof shaka.Player,
* media: {
* SegmentReference: typeof shaka.media.SegmentReference,
* InitSegmentReference: typeof shaka.media.InitSegmentReference,
* SegmentIndex: typeof shaka.media.SegmentIndex,
* PresentationTimeline: typeof shaka.media.PresentationTimeline
* },
* net: {
* NetworkingEngine: typeof shaka.net.NetworkingEngine
* },
* offline: {
* Storage: typeof shaka.offline.Storage
* },
* ui: {
* Overlay: typeof shaka.ui.Overlay,
* Controls: typeof shaka.ui.Controls,
* Element: typeof shaka.ui.Element
* },
* util: {
* StringUtils: typeof shaka.util.StringUtils
* }
* }}
*/
let shakaNamespaceType;


shaka.test.Loader = class {
/**
* @param {boolean} loadUncompiled
* @return {!Promise<shakaNamespaceType>}
* @return {!Promise<shaka>}
*/
static async loadShaka(loadUncompiled) {
/** @type {!Promise.PromiseWithResolvers} */
const loaded = Promise.withResolvers();
/** @type {shakaNamespaceType} */
/** @type {shaka} */
let compiledShaka;

if (loadUncompiled) {
Expand Down
6 changes: 3 additions & 3 deletions test/test/util/manifest_generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
shaka.test.ManifestGenerator = class {
/**
* @param {function(!shaka.test.ManifestGenerator.Manifest)=} func
* @param {shakaNamespaceType=} compiledShaka
* @param {shaka=} compiledShaka
* @return {shaka.extern.Manifest}
*/
static generate(func, compiledShaka) {
Expand Down Expand Up @@ -71,9 +71,9 @@ shaka.test.ManifestGenerator = class {
};

shaka.test.ManifestGenerator.Manifest = class {
/** @param {shakaNamespaceType=} compiledShaka */
/** @param {shaka=} compiledShaka */
constructor(compiledShaka) {
/** @private {shakaNamespaceType} */
/** @private {shaka} */
this.shaka_ = compiledShaka || window['shaka'];

/** @type {!Array<shaka.extern.Variant>} */
Expand Down
2 changes: 1 addition & 1 deletion test/test/util/test_scheme.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ shaka.test.TestScheme = class {

/**
* Creates the manifests and generators.
* @param {shakaNamespaceType} compiledShaka
* @param {shaka} compiledShaka
* @param {string} suffix
* @return {!Promise}
*/
Expand Down
6 changes: 4 additions & 2 deletions test/ui/ui_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('UI', () => {
let ui;
/** @type {!shaka.ui.Controls} */
let controls;
/** @type {shakaNamespaceType} */
/** @type {shaka} */
let compiledShaka;
/** @type {!Array<string>|undefined} */
let savedLanguages;
Expand Down Expand Up @@ -759,8 +759,10 @@ describe('UI', () => {
videoContainer, fakeControls);
uncompiledElement.release();

/** @type {typeof shaka.ui.Element} */
const CompiledElement = compiledShaka.ui.Element;
/** @extends {shaka.ui.Element} */
const TestElement = class extends compiledShaka.ui.Element {
const TestElement = class extends CompiledElement {
/**
* @param {!HTMLElement} parent
* @param {!shaka.ui.Controls} controls
Expand Down
2 changes: 1 addition & 1 deletion test/ui/vr_ui_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('VR UI', () => {
let ui;
/** @type {!shaka.ui.Controls} */
let controls;
/** @type {shakaNamespaceType} */
/** @type {shaka} */
let compiledShaka;
/** @type {boolean} */
let canPlayVR;
Expand Down
Loading