Skip to content

Commit

Permalink
Fix missing or bad type info
Browse files Browse the repository at this point in the history
In many places, the implicit type info was insufficient.  For example,
document.createElement returns Element, but the actual return is
always a subclass of Element.  In many cases, we need the compiler to
know that a specific subclass is in use, so that it can correctly
check our use of subclass-specific properties.  Another common pattern
is confusion between Node and Element (which is a subclass of Node).

Almost all of the changes in the demo and UI are Element-related.

In some places, we referred to HTMLMediaElement, used in the Player
API, instead of the more specific HTMLVideoElement in use in our demo.
Since the demo uses video-specific properties, we must use the more
specific type.

Another case is the use of document.createEvent, which returns Event
according to the compiler, but in reality always returns a subclass,
like CustomEvent.

In one case in NetworkingEngine, correcting the type of an
AbortableOperation led to the discovery that we had been incorrectly
accessing a private method of that type.

In goog.Uri, there were several instances of "*" for a type, which the
newer compiler won't accept.  These have all been corrected.

Finally, in some places, we had the wrong nullability on a type.

These were all caught by a compiler upgrade.

Issue shaka-project#2528

Change-Id: I7f2d070e3da32fe9ff5f444315649f3cbdb5a4a5
  • Loading branch information
joeyparrish committed Apr 28, 2020
1 parent 34cde38 commit 07335d7
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 65 deletions.
23 changes: 16 additions & 7 deletions demo/asset_card.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,18 @@ shakaDemo.AssetCard = class {
if (asset.iconUri) {
const picture = document.createElement('picture');

const webpSource = document.createElement('source');
const webpSource =
/** @type {!HTMLSourceElement} */(document.createElement('source'));
webpSource.srcset = asset.iconUri.replace(/.png$/, '.webp');
webpSource.type = 'image/webp';

const pngSource = document.createElement('source');
const pngSource =
/** @type {!HTMLSourceElement} */(document.createElement('source'));
pngSource.srcset = asset.iconUri;
pngSource.type = 'image/png';

const img = document.createElement('img');
const img =
/** @type {!HTMLImageElement} */(document.createElement('img'));
img.src = asset.iconUri;
img.alt = ''; // Not necessary to understand the page

Expand Down Expand Up @@ -291,7 +294,7 @@ shakaDemo.AssetCard = class {
}

/**
* @param {!Element} deleteButton
* @param {!HTMLButtonElement} deleteButton
* @private
*/
attachDeleteDialog_(deleteButton) {
Expand All @@ -314,7 +317,8 @@ shakaDemo.AssetCard = class {
* @private
*/
makeYesNoDialogue_(parentDiv, text, callback) {
const dialog = document.createElement('dialog');
const dialog =
/** @type {!HTMLDialogElement} */(document.createElement('dialog'));
dialog.classList.add('mdl-dialog');
parentDiv.appendChild(dialog);
if (!dialog.showModal) {
Expand Down Expand Up @@ -360,11 +364,15 @@ shakaDemo.AssetCard = class {
if (this.asset_.storedProgress < 1) {
this.progressCircle_.classList.remove('hidden');
for (const button of this.actions_.childNodes) {
goog.asserts.assert(
button instanceof HTMLButtonElement, 'Wrong node type!');
button.disabled = true;
}
} else {
this.progressCircle_.classList.add('hidden');
for (const button of this.actions_.childNodes) {
goog.asserts.assert(
button instanceof HTMLButtonElement, 'Wrong node type!');
button.disabled = false;
}
}
Expand All @@ -377,10 +385,11 @@ shakaDemo.AssetCard = class {
* @param {?shakaDemo.MessageIds} name
* @param {function()} onclick
* @param {shakaDemo.MessageIds=} yesNoDialogText
* @return {!Element}
* @return {!HTMLButtonElement}
*/
addButton(name, onclick, yesNoDialogText) {
const button = document.createElement('button');
const button =
/** @type {!HTMLButtonElement} */(document.createElement('button'));
button.classList.add('mdl-button');
button.classList.add('mdl-button--colored');
button.classList.add('mdl-js-button');
Expand Down
13 changes: 6 additions & 7 deletions demo/cast_receiver/receiver_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ goog.require('goog.asserts');
*/
class ShakaReceiverApp {
constructor() {
/** @private {HTMLMediaElement} */
/** @private {HTMLVideoElement} */
this.video_ = null;

/** @private {shaka.Player} */
Expand All @@ -32,15 +32,14 @@ class ShakaReceiverApp {
* Initialize the application.
*/
init() {
/** @type {HTMLMediaElement} */
const video = /** @type {HTMLMediaElement} */
(document.getElementById('video'));
goog.asserts.assert(video, 'Video element should be available!');
const video = document.getElementById('video');
goog.asserts.assert(
video instanceof HTMLVideoElement, 'Wrong element type!');
this.video_ = video;

/** @type {!shaka.ui.Overlay} */
const ui = this.video_['ui'];
goog.asserts.assert(ui, 'UI should be available!');
goog.asserts.assert(
ui instanceof shaka.ui.Overlay, 'UI not present or wrong type!');

// Make sure we don't show extra UI elements we don't need on the TV.
ui.configure({
Expand Down
8 changes: 4 additions & 4 deletions demo/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ shakaDemo.Config = class {

/**
* @param {!shakaDemo.MessageIds} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {shakaDemo.MessageIds=} tooltipMessage
* @return {!shakaDemo.Config}
* @private
Expand Down Expand Up @@ -531,7 +531,7 @@ shakaDemo.Config = class {

/**
* @param {!shakaDemo.MessageIds} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {shakaDemo.MessageIds=} tooltipMessage
* @return {!shakaDemo.Config}
* @private
Expand Down Expand Up @@ -595,7 +595,7 @@ shakaDemo.Config = class {
/**
* @param {!shakaDemo.MessageIds} name
* @param {!Array.<string>} values
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {shakaDemo.MessageIds=} tooltipMessage
* @return {!shakaDemo.Config}
* @private
Expand All @@ -611,7 +611,7 @@ shakaDemo.Config = class {
/**
* @param {!shakaDemo.MessageIds} name
* @param {!Object.<string, string>} values
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {shakaDemo.MessageIds=} tooltipMessage
* @return {!shakaDemo.Config}
* @private
Expand Down
19 changes: 14 additions & 5 deletions demo/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ shakaDemo.Custom = class {

/** @param {!Element} container */
constructor(container) {
/** @private {!Element} */
this.dialog_ = document.createElement('dialog');
/** @private {!HTMLDialogElement} */
this.dialog_ =
/** @type {!HTMLDialogElement} */(document.createElement('dialog'));

this.dialog_.classList.add('mdl-dialog');
container.appendChild(this.dialog_);
if (!this.dialog_.showModal) {
Expand Down Expand Up @@ -269,22 +271,28 @@ shakaDemo.Custom = class {
const iconSetup = (input, container) => {
if (assetInProgress.iconUri) {
input.value = assetInProgress.iconUri;
const img = document.createElement('img');

const img =
/** @type {!HTMLImageElement} */(document.createElement('img'));
img.src = input.value;
img.alt = ''; // Not necessary to understand the page
iconDiv.appendChild(img);
}
};

const iconOnChange = (input) => {
shaka.util.Dom.removeAllChildren(iconDiv);
assetInProgress.iconUri = input.value;

if (input.value) {
const img = document.createElement('img');
const img =
/** @type {!HTMLImageElement} */(document.createElement('img'));
img.src = input.value;
img.alt = ''; // Not necessary to understand the page
iconDiv.appendChild(img);
}
};

const iconURLName = shakaDemoMain.getLocalizedString(
shakaDemo.MessageIds.ICON_URL);
makeField(iconURLName, iconSetup, iconOnChange);
Expand Down Expand Up @@ -323,7 +331,8 @@ shakaDemo.Custom = class {
loadAssetInfos_() {
const savedString = window.localStorage.getItem(shakaDemo.Custom.saveId_);
if (savedString) {
const assets = JSON.parse(savedString);
const assets =
/** @type {!Array.<!ShakaDemoAssetInfo>} */(JSON.parse(savedString));
return new Set(assets.map((json) => {
const asset = ShakaDemoAssetInfo.fromJSON(json);
shakaDemoMain.setupOfflineSupport(asset);
Expand Down
22 changes: 12 additions & 10 deletions demo/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ shakaDemo.Input = class {
* the input object.
* @param {string} extraType The element type for the "sibling element" to the
* input object. If null, it adds no such element.
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
*/
constructor(parentContainer, inputType, containerType, extraType, onChange) {
/** @private {!Element} */
this.container_ = document.createElement(containerType);
parentContainer.latestElementContainer.appendChild(this.container_);

/** @private {!Element} */
this.input_ = document.createElement(inputType);
/** @private {!HTMLInputElement} */
this.input_ =
/** @type {!HTMLInputElement} */(document.createElement(inputType));
this.input_.onchange = () => {
onChange(this.input_);
};
Expand Down Expand Up @@ -61,7 +62,7 @@ shakaDemo.Input = class {
}
}

/** @return {!Element} */
/** @return {!HTMLInputElement} */
input() {
return this.input_;
}
Expand Down Expand Up @@ -100,7 +101,7 @@ shakaDemo.SelectInput = class extends shakaDemo.Input {
/**
* @param {!shakaDemo.InputContainer} parentContainer
* @param {?shakaDemo.MessageIds} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {!Object.<string, string>} values
*/
constructor(parentContainer, name, onChange, values) {
Expand All @@ -115,7 +116,8 @@ shakaDemo.SelectInput = class extends shakaDemo.Input {
this.extra_.textContent = shakaDemoMain.getLocalizedString(name);
}
for (const value of Object.keys(values)) {
const option = document.createElement('option');
const option =
/** @type {!HTMLOptionElement} */(document.createElement('option'));
option.textContent = values[value];
option.value = value;
this.input_.appendChild(option);
Expand All @@ -131,7 +133,7 @@ shakaDemo.BoolInput = class extends shakaDemo.Input {
/**
* @param {!shakaDemo.InputContainer} parentContainer
* @param {string} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
*/
constructor(parentContainer, name, onChange) {
super(parentContainer, 'input', 'label', 'span', onChange);
Expand All @@ -153,7 +155,7 @@ shakaDemo.TextInput = class extends shakaDemo.Input {
/**
* @param {!shakaDemo.InputContainer} parentContainer
* @param {string} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
*/
constructor(parentContainer, name, onChange) {
super(parentContainer, 'input', 'div', 'label', onChange);
Expand All @@ -174,7 +176,7 @@ shakaDemo.DatalistInput = class extends shakaDemo.TextInput {
/**
* @param {!shakaDemo.InputContainer} parentContainer
* @param {string} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {!Array.<string>} values
*/
constructor(parentContainer, name, onChange, values) {
Expand Down Expand Up @@ -206,7 +208,7 @@ shakaDemo.NumberInput = class extends shakaDemo.TextInput {
/**
* @param {!shakaDemo.InputContainer} parentContainer
* @param {string} name
* @param {function(!Element)} onChange
* @param {function(!HTMLInputElement)} onChange
* @param {boolean} canBeDecimal
* @param {boolean} canBeZero
* @param {boolean} canBeUnset
Expand Down
4 changes: 3 additions & 1 deletion demo/input_container.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,18 @@ shakaDemo.InputContainer = class {
* @private
*/
addDocLink_(parentDiv, docLink) {
const link = document.createElement('a');
const link = /** @type {!HTMLAnchorElement} */(document.createElement('a'));
link.href = docLink;
link.target = '_blank';
link.classList.add('mdl-button');
link.classList.add('mdl-js-button');
link.classList.add('mdl-js-ripple-effect');
link.classList.add('mdl-button--colored');

const icon = document.createElement('i');
icon.classList.add('material-icons');
icon.textContent = 'help';

link.appendChild(icon);
parentDiv.appendChild(link);
}
Expand Down
Loading

0 comments on commit 07335d7

Please sign in to comment.