Skip to content

Commit

Permalink
Enable strict null checking and fix...everything
Browse files Browse the repository at this point in the history
  • Loading branch information
rcebulko committed Dec 8, 2021
1 parent 80a13bb commit 06e7268
Show file tree
Hide file tree
Showing 26 changed files with 154 additions and 94 deletions.
9 changes: 5 additions & 4 deletions src/core/assert.shame.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
declare module '#core/assert' {
function devAssert<T>(T, string?, ...any): T;
function userAssert<T>(T, string?, ...any): T;
function devAssertElement<T>(T, string?, ...any): HTMLElement;
function devAssertString<T>(T, string?, ...any): string;
function devAssert<T>(subject: T | null | undefined, msg?: string, ...any): T;
function userAssert<T>(subject: T | null | undefined, msg?: string, ...any): T;
function devAssertElement<T>(subject: T, msg?: string, ...any): HTMLElement;
function devAssertString<T>(subject: T, msg?: string, ...any): string;
function devAssertNumber<T>(subject: T, msg?: string, ...any): number;
}
2 changes: 1 addition & 1 deletion src/core/data-structures/lru-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class LruCache {

/**
* @param {number|string} key
* @return {T} The cached payload.
* @return {T|undefined} The cached payload.
*/
get(key) {
const cacheable = this.cache_[key];
Expand Down
6 changes: 3 additions & 3 deletions src/core/data-structures/observable.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ export class Observable {
* Creates an instance of Observable.
*/
constructor() {
/** @type {?Array<function(TYPE):void>} */
/** @type {?Array<function(TYPE=):void>} */
this.handlers_ = null;
}

/**
* Adds the observer to this instance.
* @param {function(TYPE):void} handler Observer's handler.
* @param {function(TYPE=):void} handler Observer's handler.
* @return {UnlistenCallback}
*/
add(handler) {
Expand All @@ -31,7 +31,7 @@ export class Observable {

/**
* Removes the observer from this instance.
* @param {function(TYPE):void} handler Observer's instance.
* @param {function(TYPE=):void} handler Observer's instance.
*/
remove(handler) {
if (!this.handlers_) {
Expand Down
4 changes: 2 additions & 2 deletions src/core/data-structures/priority-queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class PriorityQueue {

/**
* Returns the max priority item without dequeueing it.
* @return {T}
* @return {?T}
*/
peek() {
const l = this.length;
Expand Down Expand Up @@ -79,7 +79,7 @@ export class PriorityQueue {
/**
* Dequeues the max priority item.
* Items with the same priority are dequeued in FIFO order.
* @return {T}
* @return {?T}
*/
dequeue() {
if (!this.length) {
Expand Down
36 changes: 30 additions & 6 deletions src/core/dom/event-helper-listen.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ export function internalListenImplementation(
optsSupported ? opt_evtListenerOpts : capture
);
// Ensure these are GC'd
localListener = null;
localElement = null;
/** @type {?} */ (localListener) = null;
/** @type {?} */ (localElement) = null;
wrapped = null;
};
}
Expand All @@ -95,8 +95,20 @@ export function detectEvtListenerOptsSupport() {
return false;
},
};
self.addEventListener('test-options', null, options);
self.removeEventListener('test-options', null, options);
self.addEventListener(
'test-options',
/** @type {EventListenerOrEventListenerObject} */ (
/** @type {?} */ (null)
),
options
);
self.removeEventListener(
'test-options',
/** @type {EventListenerOrEventListenerObject} */ (
/** @type {?} */ (null)
),
options
);
} catch (err) {
// EventListenerOptions are not supported
}
Expand Down Expand Up @@ -132,8 +144,20 @@ export function supportsPassiveEventListener(win) {
},
});

win.addEventListener('test-options', null, options);
win.removeEventListener('test-options', null, options);
win.addEventListener(
'test-options',
/** @type {EventListenerOrEventListenerObject} */ (
/** @type {?} */ (null)
),
options
);
win.removeEventListener(
'test-options',
/** @type {EventListenerOrEventListenerObject} */ (
/** @type {?} */ (null)
),
options
);
} catch (err) {
// EventListenerOptions are not supported
}
Expand Down
4 changes: 3 additions & 1 deletion src/core/dom/event.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export {};

declare global {
interface Event {
data?: Object;
// We assign an `Object` at times, though Typescript's dom lib supports
// string or null, so here we allow all three (plus unedfined).
data?: Object | string | null;
}
}
4 changes: 2 additions & 2 deletions src/core/dom/get-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ function appendToResult(rootNode, attrs, result) {
const allowedAttrs = attrs.filter((attr) => allowedAttributes.includes(attr));

while (stack.length > 0) {
const node = stack.pop();
const node = /** @type {string|Element} */ (stack.pop());

if (isString(node)) {
result.push(node);
} else if (node.nodeType === Node.TEXT_NODE) {
result.push(node.textContent);
result.push(node.textContent ?? '');
} else if (isElement(node) && isApplicableNode(node)) {
appendOpenTag(node, allowedAttrs, result);
stack.push(`</${node.tagName.toLowerCase()}>`);
Expand Down
2 changes: 1 addition & 1 deletion src/core/dom/img.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
export function guaranteeSrcForSrcsetUnsupportedBrowsers(img) {
// The <img> tag does not have a src and does not support srcset
if (!img.hasAttribute('src') && 'srcset' in img == false) {
const srcset = img.getAttribute('srcset');
const srcset = img.getAttribute('srcset') || '';
const matches = /\S+/.exec(srcset);
if (matches == null) {
return;
Expand Down
12 changes: 8 additions & 4 deletions src/core/dom/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {devAssert} from '#core/assert';
import * as mode from '#core/mode';
import {dict} from '#core/types/object';
import {parseJson} from '#core/types/object/json';
Expand Down Expand Up @@ -205,9 +206,11 @@ export function isConnectedNode(node) {
* @return {ShadowRoot|Document}
*/
export function rootNodeFor(node) {
// https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode
// @ts-ignore this always is truthy according to TS, but isn't in IE 11.
if (Node.prototype.getRootNode) {
// Type checker says `getRootNode` may return null.
return /** @type {ShadowRoot|Document} */ (node.getRootNode() || node);
return /** @type {ShadowRoot|Document} */ (node.getRootNode());
}
let n;
// Check isShadowRoot() is only needed for the polyfill case.
Expand Down Expand Up @@ -277,6 +280,7 @@ export function getDataParamsFromAttributes(
* @return {boolean}
*/
export function hasNextNodeInDocumentOrder(element, opt_stopNode) {
/** @type {?Element} */
let currentElement = element;
do {
if (currentElement.nextSibling) {
Expand Down Expand Up @@ -504,7 +508,7 @@ export function getVerticalScrollbarWidth(win) {
export function dispatchCustomEvent(node, name, opt_data, opt_options) {
const data = opt_data || {};
// Constructors of events need to come from the correct window. Sigh.
const event = node.ownerDocument.createEvent('Event');
const event = devAssert(node.ownerDocument).createEvent('Event');

// Technically .data is not a property of Event.
event.data = data;
Expand Down Expand Up @@ -545,7 +549,7 @@ export function getChildJsonConfig(element) {
}

try {
return parseJson(script.textContent);
return parseJson(script.textContent ?? '');
} catch {
throw new Error('Failed to parse <script> contents. Is it valid JSON?');
}
Expand All @@ -572,6 +576,6 @@ export function propagateNonce(doc, scriptEl) {
const currentScript = doc.head.querySelector('script[nonce]');
if (currentScript) {
const nonce = currentScript.nonce || currentScript.getAttribute('nonce');
scriptEl.setAttribute('nonce', nonce);
scriptEl.setAttribute('nonce', nonce ?? '');
}
}
6 changes: 4 additions & 2 deletions src/core/dom/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ export function parseLength(s) {
*/
export function assertLength(length) {
userAssert(
/^\d+(\.\d+)?(px|em|rem|vh|vw|vmin|vmax|cm|mm|q|in|pc|pt)$/.test(length),
/^\d+(\.\d+)?(px|em|rem|vh|vw|vmin|vmax|cm|mm|q|in|pc|pt)$/.test(
length ?? ''
),
'Invalid length value: %s',
length
);
Expand Down Expand Up @@ -189,7 +191,7 @@ export function assertLengthOrPercent(length) {
export function getLengthUnits(length) {
assertLength(length);
const m = userAssert(
/[a-z]+/i.exec(length),
/[a-z]+/i.exec(length ?? ''),
'Failed to read units from %s',
length
);
Expand Down
19 changes: 10 additions & 9 deletions src/core/dom/layout/intersection-no-root.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {devAssert} from '#core/assert';
import {Deferred} from '#core/data-structures/promise';
import {createViewportObserver} from '#core/dom/layout/viewport-observer';
import {getWin} from '#core/window';
Expand All @@ -12,10 +13,10 @@ import {getWin} from '#core/window';
* support is better.
*/

/** @type {WeakMap<Element, Deferred<IntersectionObserverEntry>>} */
/** @type {undefined|WeakMap<Element, Deferred<IntersectionObserverEntry>>} */
let intersectionDeferreds;

/** @type {WeakMap<Window, IntersectionObserver>} */
/** @type {undefined|WeakMap<Window, IntersectionObserver>} */
let intersectionObservers;

/**
Expand All @@ -28,7 +29,7 @@ function getInOb(win) {
intersectionObservers = new WeakMap();
}

let observer = intersectionObservers.get(win);
let observer = devAssert(intersectionObservers).get(win);
if (!observer) {
observer = createViewportObserver(
(entries) => {
Expand All @@ -40,15 +41,15 @@ function getInOb(win) {
}
seen.add(target);

observer.unobserve(target);
intersectionDeferreds.get(target).resolve(entries[i]);
intersectionDeferreds.delete(target);
devAssert(observer).unobserve(target);
devAssert(intersectionDeferreds).get(target)?.resolve(entries[i]);
devAssert(intersectionDeferreds).delete(target);
}
},
win,
{needsRootBounds: false}
);
intersectionObservers.set(win, observer);
devAssert(intersectionObservers).set(win, observer);
}
return observer;
}
Expand All @@ -64,13 +65,13 @@ function getInOb(win) {
*/
export function measureIntersectionNoRoot(el) {
if (intersectionDeferreds?.has(el)) {
return intersectionDeferreds.get(el).promise;
return devAssert(intersectionDeferreds.get(el)).promise;
}

const inOb = getInOb(getWin(el));
inOb.observe(el);

const deferred = new Deferred();
intersectionDeferreds.set(el, deferred);
devAssert(intersectionDeferreds).set(el, deferred);
return deferred.promise;
}
21 changes: 11 additions & 10 deletions src/core/dom/layout/intersection.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {devAssert} from '#core/assert';
import {Deferred} from '#core/data-structures/promise';
import {dict} from '#core/types/object';
import {getWin} from '#core/window';

import {LayoutRectDef, layoutRectFromDomRect} from './rect';
import {createViewportObserver} from './viewport-observer';

/** @type {WeakMap<Element, Deferred<IntersectionObserverEntry>>|undefined} */
/** @type {undefined|WeakMap<Element, Deferred<IntersectionObserverEntry>>|undefined} */
let intersectionDeferreds;

/** @type {WeakMap<Window, IntersectionObserver>|undefined} */
/** @type {undefined|WeakMap<Window, IntersectionObserver>|undefined} */
let intersectionObservers;

/**
Expand All @@ -21,7 +22,7 @@ function getInOb(win) {
intersectionObservers = new WeakMap();
}

let observer = intersectionObservers.get(win);
let observer = devAssert(intersectionObservers).get(win);
if (!observer) {
observer = createViewportObserver(
(entries) => {
Expand All @@ -33,15 +34,15 @@ function getInOb(win) {
}
seen.add(target);

observer.unobserve(target);
intersectionDeferreds.get(target).resolve(entries[i]);
intersectionDeferreds.delete(target);
devAssert(observer).unobserve(target);
devAssert(intersectionDeferreds).get(target)?.resolve(entries[i]);
devAssert(intersectionDeferreds).delete(target);
}
},
win,
{needsRootBounds: true}
);
intersectionObservers.set(win, observer);
devAssert(intersectionObservers).set(win, observer);
}
return observer;
}
Expand All @@ -56,15 +57,15 @@ function getInOb(win) {
* @return {Promise<IntersectionObserverEntry>}
*/
export function measureIntersection(el) {
if (intersectionDeferreds && intersectionDeferreds.has(el)) {
return intersectionDeferreds.get(el).promise;
if (intersectionDeferreds?.has(el)) {
return devAssert(intersectionDeferreds.get(el)).promise;
}

const inOb = getInOb(getWin(el));
inOb.observe(el);

const deferred = new Deferred();
intersectionDeferreds.set(el, deferred);
devAssert(intersectionDeferreds).set(el, deferred);
return deferred.promise;
}

Expand Down
12 changes: 7 additions & 5 deletions src/core/dom/media-query-props.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @typedef {Array<{query: ?MediaQueryList, value: string}>} */
let ExprDef;
import {devAssert} from '#core/assert';

/** @typedef {Array<{query: ?MediaQueryList, value: string}>} ExprDef */

const TRUE_VALUE = '1';

Expand Down Expand Up @@ -37,7 +38,7 @@ export class MediaQueryProps {
*/
resolveMatchQuery(queryString) {
// This will create a list query like this:
// `[{query: matchMedia(queryString), value: true}, {query: null, value: false}]`
// `[{query: matchMedia(queryHeadString), value: true}, {query: null, value: false}]`
return (
this.resolve_(queryString, parseMediaQueryMatchExpr, TRUE_VALUE) ===
TRUE_VALUE
Expand Down Expand Up @@ -85,7 +86,8 @@ export class MediaQueryProps {
if (!exprString.trim()) {
return emptyExprValue;
}
let expr = this.exprMap_[exprString] || this.prevExprMap_[exprString];
let expr =
this.exprMap_[exprString] || devAssert(this.prevExprMap_)[exprString];
if (!expr) {
expr = parser(this.win_, exprString);
toggleOnChange(expr, this.callback_, true);
Expand Down Expand Up @@ -114,7 +116,7 @@ function parseMediaQueryMatchExpr(win, queryString) {
* @return {ExprDef}
*/
function parseMediaQueryListExpr(win, exprString) {
return (
return /** @type {ExprDef} */ (
exprString
.split(',')
.map((part) => {
Expand Down
Loading

0 comments on commit 06e7268

Please sign in to comment.