From 4da4827bcbcdd1ef163f635d9b29416ff272b0bb Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 12:48:14 -0500 Subject: Add JSDoc type annotations to project (rebased) --- ext/js/app/popup.js | 333 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 234 insertions(+), 99 deletions(-) (limited to 'ext/js/app/popup.js') diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js index 0e2e2493..31b18f01 100644 --- a/ext/js/app/popup.js +++ b/ext/js/app/popup.js @@ -25,53 +25,12 @@ import {ThemeController} from './theme-controller.js'; /** * This class is the container which hosts the display of search results. + * @augments EventDispatcher */ export class Popup extends EventDispatcher { - /** - * Information about how popup content should be shown, specifically related to the outer popup frame. - * @typedef {object} ContentDetails - * @property {?object} optionsContext The options context for the content to show. - * @property {Rect[]} sourceRects The rectangles of the source content. - * @property {'horizontal-tb' | 'vertical-rl' | 'vertical-lr' | 'sideways-rl' | 'sideways-lr'} writingMode The normalized CSS writing-mode value of the source content. - */ - - /** - * A rectangle representing a DOM region, similar to DOMRect. - * @typedef {object} Rect - * @property {number} left The left position of the rectangle. - * @property {number} top The top position of the rectangle. - * @property {number} right The right position of the rectangle. - * @property {number} bottom The bottom position of the rectangle. - */ - - /** - * A rectangle representing a DOM region, similar to DOMRect but with a `valid` property. - * @typedef {object} ValidRect - * @property {number} left The left position of the rectangle. - * @property {number} top The top position of the rectangle. - * @property {number} right The right position of the rectangle. - * @property {number} bottom The bottom position of the rectangle. - * @property {boolean} valid Whether or not the rectangle is valid. - */ - - /** - * A rectangle representing a DOM region for placing the popup frame. - * @typedef {object} SizeRect - * @property {number} left The left position of the rectangle. - * @property {number} top The top position of the rectangle. - * @property {number} width The width of the rectangle. - * @property {number} height The height of the rectangle. - * @property {boolean} after Whether or not the rectangle is positioned to the right of the source rectangle. - * @property {boolean} below Whether or not the rectangle is positioned below the source rectangle. - */ - /** * Creates a new instance. - * @param {object} details The details used to construct the new instance. - * @param {string} details.id The ID of the popup. - * @param {number} details.depth The depth of the popup. - * @param {number} details.frameId The ID of the host frame. - * @param {boolean} details.childrenSupported Whether or not the popup is able to show child popups. + * @param {import('popup').PopupConstructorDetails} details The details used to construct the new instance. */ constructor({ id, @@ -80,48 +39,83 @@ export class Popup extends EventDispatcher { childrenSupported }) { super(); + /** @type {string} */ this._id = id; + /** @type {number} */ this._depth = depth; + /** @type {number} */ this._frameId = frameId; + /** @type {boolean} */ this._childrenSupported = childrenSupported; + /** @type {?Popup} */ this._parent = null; + /** @type {?Popup} */ this._child = null; + /** @type {?Promise} */ this._injectPromise = null; + /** @type {boolean} */ this._injectPromiseComplete = false; + /** @type {DynamicProperty} */ this._visible = new DynamicProperty(false); + /** @type {boolean} */ this._visibleValue = false; + /** @type {?import('settings').OptionsContext} */ this._optionsContext = null; + /** @type {number} */ this._contentScale = 1.0; + /** @type {string} */ this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, ''); - this._optionsAssigned = false; + /** @type {number} */ this._initialWidth = 400; + /** @type {number} */ this._initialHeight = 250; + /** @type {number} */ this._horizontalOffset = 0; + /** @type {number} */ this._verticalOffset = 10; + /** @type {number} */ this._horizontalOffset2 = 10; + /** @type {number} */ this._verticalOffset2 = 0; + /** @type {import('settings').PopupVerticalTextPosition} */ this._verticalTextPosition = 'before'; + /** @type {boolean} */ this._horizontalTextPositionBelow = true; + /** @type {import('settings').PopupDisplayMode} */ this._displayMode = 'default'; + /** @type {boolean} */ this._displayModeIsFullWidth = false; + /** @type {boolean} */ this._scaleRelativeToVisualViewport = true; + /** @type {boolean} */ this._useSecureFrameUrl = true; + /** @type {boolean} */ this._useShadowDom = true; + /** @type {string} */ this._customOuterCss = ''; + /** @type {?number} */ this._frameSizeContentScale = null; + /** @type {?FrameClient} */ this._frameClient = null; + /** @type {HTMLIFrameElement} */ this._frame = document.createElement('iframe'); this._frame.className = 'yomitan-popup'; this._frame.style.width = '0'; this._frame.style.height = '0'; + /** @type {boolean} */ + this._frameConnected = false; + /** @type {HTMLElement} */ this._container = this._frame; + /** @type {?ShadowRoot} */ this._shadow = null; + /** @type {ThemeController} */ this._themeController = new ThemeController(this._frame); + /** @type {EventListenerCollection} */ this._fullscreenEventListeners = new EventListenerCollection(); } @@ -135,7 +129,7 @@ export class Popup extends EventDispatcher { /** * The parent of the popup. - * @type {Popup} + * @type {?Popup} */ get parent() { return this._parent; @@ -151,7 +145,7 @@ export class Popup extends EventDispatcher { /** * The child of the popup. - * @type {Popup} + * @type {?Popup} */ get child() { return this._child; @@ -167,7 +161,7 @@ export class Popup extends EventDispatcher { /** * The depth of the popup. - * @type {numer} + * @type {number} */ get depth() { return this._depth; @@ -215,11 +209,13 @@ export class Popup extends EventDispatcher { /** * Sets the options context for the popup. - * @param {object} optionsContext The options context object. + * @param {import('settings').OptionsContext} optionsContext The options context object. */ async setOptionsContext(optionsContext) { await this._setOptionsContext(optionsContext); - await this._invokeSafe('Display.setOptionsContext', {optionsContext}); + if (this._frameConnected) { + await this._invokeSafe('Display.setOptionsContext', {optionsContext}); + } } /** @@ -252,7 +248,7 @@ export class Popup extends EventDispatcher { * Force assigns the visibility of the popup. * @param {boolean} value Whether or not the popup should be visible. * @param {number} priority The priority of the override. - * @returns {Promise} A token used which can be passed to `clearVisibleOverride`, + * @returns {Promise} A token used which can be passed to `clearVisibleOverride`, * or null if the override wasn't assigned. */ async setVisibleOverride(value, priority) { @@ -261,7 +257,7 @@ export class Popup extends EventDispatcher { /** * Clears a visibility override that was generated by `setVisibleOverride`. - * @param {string} token The token returned from `setVisibleOverride`. + * @param {import('core').TokenString} token The token returned from `setVisibleOverride`. * @returns {Promise} `true` if the override existed and was removed, `false` otherwise. */ async clearVisibleOverride(token) { @@ -275,7 +271,8 @@ export class Popup extends EventDispatcher { * @returns {Promise} `true` if the point is contained within the popup's rect, `false` otherwise. */ async containsPoint(x, y) { - for (let popup = this; popup !== null && popup.isVisibleSync(); popup = popup.child) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + for (let popup = /** @type {?Popup} */ (this); popup !== null && popup.isVisibleSync(); popup = popup.child) { const rect = popup.getFrameRect(); if (rect.valid && x >= rect.left && y >= rect.top && x < rect.right && y < rect.bottom) { return true; @@ -286,12 +283,12 @@ export class Popup extends EventDispatcher { /** * Shows and updates the positioning and content of the popup. - * @param {ContentDetails} details Settings for the outer popup. - * @param {Display.ContentDetails} displayDetails The details parameter passed to `Display.setContent`. + * @param {import('popup').ContentDetails} details Settings for the outer popup. + * @param {?import('display').ContentDetails} displayDetails The details parameter passed to `Display.setContent`. * @returns {Promise} */ async showContent(details, displayDetails) { - if (!this._optionsAssigned) { throw new Error('Options not assigned'); } + if (this._optionsContext === null) { throw new Error('Options not assigned'); } const {optionsContext, sourceRects, writingMode} = details; if (optionsContext !== null) { @@ -309,25 +306,27 @@ export class Popup extends EventDispatcher { * Sets the custom styles for the popup content. * @param {string} css The CSS rules. */ - setCustomCss(css) { - this._invokeSafe('Display.setCustomCss', {css}); + async setCustomCss(css) { + await this._invokeSafe('Display.setCustomCss', {css}); } /** * Stops the audio auto-play timer, if one has started. */ - clearAutoPlayTimer() { - this._invokeSafe('Display.clearAutoPlayTimer'); + async clearAutoPlayTimer() { + if (this._frameConnected) { + await this._invokeSafe('Display.clearAutoPlayTimer', {}); + } } /** * Sets the scaling factor of the popup content. * @param {number} scale The scaling factor. */ - setContentScale(scale) { + async setContentScale(scale) { this._contentScale = scale; this._frame.style.fontSize = `${scale}px`; - this._invokeSafe('Display.setContentScale', {scale}); + await this._invokeSafe('Display.setContentScale', {scale}); } /** @@ -360,12 +359,14 @@ export class Popup extends EventDispatcher { parentNode = this._shadow; } const node = await dynamicLoader.loadStyle('yomitan-popup-outer-user-stylesheet', 'code', css, useWebExtensionApi, parentNode); - this.trigger('customOuterCssChanged', {node, useWebExtensionApi, inShadow}); + /** @type {import('popup').CustomOuterCssChangedEvent} */ + const event = {node, useWebExtensionApi, inShadow}; + this.trigger('customOuterCssChanged', event); } /** * Gets the rectangle of the DOM frame, synchronously. - * @returns {ValidRect} The rect. + * @returns {import('popup').ValidRect} The rect. * `valid` is `false` for `PopupProxy`, since the DOM node is hosted in a different frame. */ getFrameRect() { @@ -375,7 +376,7 @@ export class Popup extends EventDispatcher { /** * Gets the size of the DOM frame. - * @returns {Promise<{width: number, height: number, valid: boolean}>} The size and whether or not it is valid. + * @returns {Promise} The size and whether or not it is valid. */ async getFrameSize() { const {width, height} = this._getFrameBoundingClientRect(); @@ -395,14 +396,23 @@ export class Popup extends EventDispatcher { // Private functions + /** + * @returns {void} + */ _onFrameMouseOver() { this.trigger('framePointerOver', {}); } + /** + * @returns {void} + */ _onFrameMouseOut() { this.trigger('framePointerOut', {}); } + /** + * @returns {Promise} + */ _inject() { let injectPromise = this._injectPromise; if (injectPromise === null) { @@ -419,19 +429,25 @@ export class Popup extends EventDispatcher { return injectPromise; } + /** + * @returns {Promise} + */ async _injectInner1() { try { await this._injectInner2(); return true; } catch (e) { this._resetFrame(); - if (e.source === this) { return false; } // Passive error + if (e instanceof PopupError && e.source === this) { return false; } // Passive error throw e; } } + /** + * @returns {Promise} + */ async _injectInner2() { - if (!this._optionsAssigned) { + if (this._optionsContext === null) { throw new Error('Options not initialized'); } @@ -439,6 +455,7 @@ export class Popup extends EventDispatcher { await this._setUpContainer(this._useShadowDom); + /** @type {import('frame-client').SetupFrameFunction} */ const setupFrame = (frame) => { frame.removeAttribute('src'); frame.removeAttribute('srcdoc'); @@ -447,9 +464,8 @@ export class Popup extends EventDispatcher { const {contentDocument} = frame; if (contentDocument === null) { // This can occur when running inside a sandboxed frame without "allow-same-origin" - const error = new Error('Popup not supoprted in this context'); - error.source = this; // Used to detect a passive error which should be ignored - throw error; + // Custom error is used to detect a passive error which should be ignored + throw new PopupError('Popup not supported in this context', this); } const url = chrome.runtime.getURL('/popup.html'); if (useSecurePopupFrameUrl) { @@ -462,23 +478,32 @@ export class Popup extends EventDispatcher { const frameClient = new FrameClient(); this._frameClient = frameClient; await frameClient.connect(this._frame, this._targetOrigin, this._frameId, setupFrame); + this._frameConnected = true; // Configure - await this._invokeSafe('Display.configure', { + /** @type {import('display').ConfigureMessageDetails} */ + const configureParams = { depth: this._depth, parentPopupId: this._id, parentFrameId: this._frameId, childrenSupported: this._childrenSupported, scale: this._contentScale, optionsContext: this._optionsContext - }); + }; + await this._invokeSafe('Display.configure', configureParams); } + /** + * @returns {void} + */ _onFrameLoad() { if (!this._injectPromiseComplete) { return; } this._resetFrame(); } + /** + * @returns {void} + */ _resetFrame() { const parent = this._container.parentNode; if (parent !== null) { @@ -488,10 +513,14 @@ export class Popup extends EventDispatcher { this._frame.removeAttribute('srcdoc'); this._frameClient = null; + this._frameConnected = false; this._injectPromise = null; this._injectPromiseComplete = false; } + /** + * @param {boolean} usePopupShadowDom + */ async _setUpContainer(usePopupShadowDom) { if (usePopupShadowDom && typeof this._frame.attachShadow === 'function') { const container = document.createElement('div'); @@ -514,6 +543,9 @@ export class Popup extends EventDispatcher { await this._injectStyles(); } + /** + * @returns {Promise} + */ async _injectStyles() { try { await this._injectPopupOuterStylesheet(); @@ -528,7 +560,11 @@ export class Popup extends EventDispatcher { } } + /** + * @returns {Promise} + */ async _injectPopupOuterStylesheet() { + /** @type {'code'|'file'|'file-content'} */ let fileType = 'file'; let useWebExtensionApi = true; let parentNode = null; @@ -540,6 +576,9 @@ export class Popup extends EventDispatcher { await dynamicLoader.loadStyle('yomitan-popup-outer-stylesheet', fileType, '/css/popup-outer.css', useWebExtensionApi, parentNode); } + /** + * @param {boolean} observe + */ _observeFullscreen(observe) { if (!observe) { this._fullscreenEventListeners.removeAllEventListeners(); @@ -554,6 +593,9 @@ export class Popup extends EventDispatcher { DocumentUtil.addFullscreenChangeEventListener(this._onFullscreenChanged.bind(this), this._fullscreenEventListeners); } + /** + * @returns {void} + */ _onFullscreenChanged() { const parent = this._getFrameParentElement(); if (parent !== null && this._container.parentNode !== parent) { @@ -561,6 +603,10 @@ export class Popup extends EventDispatcher { } } + /** + * @param {import('popup').Rect[]} sourceRects + * @param {import('document-util').NormalizedWritingMode} writingMode + */ async _show(sourceRects, writingMode) { const injected = await this._inject(); if (!injected) { return; } @@ -588,16 +634,26 @@ export class Popup extends EventDispatcher { } } + /** + * @param {number} width + * @param {number} height + */ _setFrameSize(width, height) { const {style} = this._frame; style.width = `${width}px`; style.height = `${height}px`; } + /** + * @param {boolean} visible + */ _setVisible(visible) { this._visible.defaultValue = visible; } + /** + * @param {import('dynamic-property').ChangeEventDetails} event + */ _onVisibleChange({value}) { if (this._visibleValue === value) { return; } this._visibleValue = value; @@ -605,6 +661,9 @@ export class Popup extends EventDispatcher { this._invokeSafe('Display.visibilityChanged', {value}); } + /** + * @returns {void} + */ _focusParent() { if (this._parent !== null) { // Chrome doesn't like focusing iframe without contentWindow. @@ -621,23 +680,43 @@ export class Popup extends EventDispatcher { } } - async _invoke(action, params={}) { + /** + * @template {import('core').SerializableObject} TParams + * @template [TReturn=unknown] + * @param {string} action + * @param {TParams} params + * @returns {Promise} + */ + async _invoke(action, params) { const contentWindow = this._frame.contentWindow; - if (this._frameClient === null || !this._frameClient.isConnected() || contentWindow === null) { return; } + if (this._frameClient === null || !this._frameClient.isConnected() || contentWindow === null) { + throw new Error(`Failed to invoke action ${action}: frame state invalid`); + } const message = this._frameClient.createMessage({action, params}); return await yomitan.crossFrame.invoke(this._frameClient.frameId, 'popupMessage', message); } - async _invokeSafe(action, params={}, defaultReturnValue) { + /** + * @template {import('core').SerializableObject} TParams + * @template [TReturn=unknown] + * @param {string} action + * @param {TParams} params + * @returns {Promise} + */ + async _invokeSafe(action, params) { try { return await this._invoke(action, params); } catch (e) { if (!yomitan.isExtensionUnloaded) { throw e; } - return defaultReturnValue; + return void 0; } } + /** + * @param {string} action + * @param {import('core').SerializableObject} params + */ _invokeWindow(action, params={}) { const contentWindow = this._frame.contentWindow; if (this._frameClient === null || !this._frameClient.isConnected() || contentWindow === null) { return; } @@ -646,10 +725,16 @@ export class Popup extends EventDispatcher { contentWindow.postMessage(message, this._targetOrigin); } + /** + * @returns {void} + */ _onExtensionUnloaded() { this._invokeWindow('Display.extensionUnloaded'); } + /** + * @returns {Element} + */ _getFrameParentElement() { let defaultParent = document.body; if (defaultParent !== null && defaultParent.tagName.toLowerCase() === 'frameset') { @@ -659,7 +744,8 @@ export class Popup extends EventDispatcher { if ( fullscreenElement === null || fullscreenElement.shadowRoot || - fullscreenElement.openOrClosedShadowRoot // Available to Firefox 63+ for WebExtensions + // @ts-ignore - openOrClosedShadowRoot is available to Firefox 63+ for WebExtensions + fullscreenElement.openOrClosedShadowRoot ) { return defaultParent; } @@ -675,10 +761,10 @@ export class Popup extends EventDispatcher { /** * Computes the position where the popup should be placed relative to the source content. - * @param {Rect[]} sourceRects The rectangles of the source content. - * @param {string} writingMode The CSS writing mode of the source text. - * @param {Rect} viewport The viewport that the popup can be placed within. - * @returns {SizeRect} The calculated rectangle for where to position the popup. + * @param {import('popup').Rect[]} sourceRects The rectangles of the source content. + * @param {import('document-util').NormalizedWritingMode} writingMode The CSS writing mode of the source text. + * @param {import('popup').Rect} viewport The viewport that the popup can be placed within. + * @returns {import('popup').SizeRect} The calculated rectangle for where to position the popup. */ _getPosition(sourceRects, writingMode, viewport) { sourceRects = this._convertSourceRectsCoordinateSpace(sourceRects); @@ -705,6 +791,7 @@ export class Popup extends EventDispatcher { horizontalOffset *= contentScale; verticalOffset *= contentScale; + /** @type {?import('popup').SizeRect} */ let best = null; const sourceRectsLength = sourceRects.length; for (let i = 0, ii = (sourceRectsLength > 1 ? sourceRectsLength : 0); i <= ii; ++i) { @@ -720,19 +807,20 @@ export class Popup extends EventDispatcher { if (result.height >= frameHeight) { break; } } } - return best; + // Given the loop conditions, this is guaranteed to be non-null + return /** @type {import('popup').SizeRect} */ (best); } /** * Computes the position where the popup should be placed for horizontal text. - * @param {Rect} sourceRect The rectangle of the source content. + * @param {import('popup').Rect} sourceRect The rectangle of the source content. * @param {number} frameWidth The preferred width of the frame. * @param {number} frameHeight The preferred height of the frame. - * @param {Rect} viewport The viewport that the frame can be placed within. + * @param {import('popup').Rect} viewport The viewport that the frame can be placed within. * @param {number} horizontalOffset The horizontal offset from the source rect that the popup will be placed. * @param {number} verticalOffset The vertical offset from the source rect that the popup will be placed. * @param {boolean} preferBelow Whether or not the popup is preferred to be placed below the source content. - * @returns {SizeRect} The calculated rectangle for where to position the popup. + * @returns {import('popup').SizeRect} The calculated rectangle for where to position the popup. */ _getPositionForHorizontalText(sourceRect, frameWidth, frameHeight, viewport, horizontalOffset, verticalOffset, preferBelow) { const [left, width, after] = this._getConstrainedPosition( @@ -756,14 +844,14 @@ export class Popup extends EventDispatcher { /** * Computes the position where the popup should be placed for vertical text. - * @param {Rect} sourceRect The rectangle of the source content. + * @param {import('popup').Rect} sourceRect The rectangle of the source content. * @param {number} frameWidth The preferred width of the frame. * @param {number} frameHeight The preferred height of the frame. - * @param {Rect} viewport The viewport that the frame can be placed within. + * @param {import('popup').Rect} viewport The viewport that the frame can be placed within. * @param {number} horizontalOffset The horizontal offset from the source rect that the popup will be placed. * @param {number} verticalOffset The vertical offset from the source rect that the popup will be placed. * @param {boolean} preferRight Whether or not the popup is preferred to be placed to the right of the source content. - * @returns {SizeRect} The calculated rectangle for where to position the popup. + * @returns {import('popup').SizeRect} The calculated rectangle for where to position the popup. */ _getPositionForVerticalText(sourceRect, frameWidth, frameHeight, viewport, horizontalOffset, verticalOffset, preferRight) { const [left, width, after] = this._getConstrainedPositionBinary( @@ -785,6 +873,11 @@ export class Popup extends EventDispatcher { return {left, top, width, height, after, below}; } + /** + * @param {import('settings').PopupVerticalTextPosition} positionPreference + * @param {import('document-util').NormalizedWritingMode} writingMode + * @returns {boolean} + */ _isVerticalTextPopupOnRight(positionPreference, writingMode) { switch (positionPreference) { case 'before': @@ -799,6 +892,10 @@ export class Popup extends EventDispatcher { } } + /** + * @param {import('document-util').NormalizedWritingMode} writingMode + * @returns {boolean} + */ _isWritingModeLeftToRight(writingMode) { switch (writingMode) { case 'vertical-lr': @@ -809,6 +906,15 @@ export class Popup extends EventDispatcher { } } + /** + * @param {number} positionBefore + * @param {number} positionAfter + * @param {number} size + * @param {number} minLimit + * @param {number} maxLimit + * @param {boolean} after + * @returns {[position: number, size: number, after: boolean]} + */ _getConstrainedPosition(positionBefore, positionAfter, size, minLimit, maxLimit, after) { size = Math.min(size, maxLimit - minLimit); @@ -824,6 +930,15 @@ export class Popup extends EventDispatcher { return [position, size, after]; } + /** + * @param {number} positionBefore + * @param {number} positionAfter + * @param {number} size + * @param {number} minLimit + * @param {number} maxLimit + * @param {boolean} after + * @returns {[position: number, size: number, after: boolean]} + */ _getConstrainedPositionBinary(positionBefore, positionAfter, size, minLimit, maxLimit, after) { const overflowBefore = minLimit - (positionBefore - size); const overflowAfter = (positionAfter + size) - maxLimit; @@ -847,11 +962,11 @@ export class Popup extends EventDispatcher { /** * Gets the visual viewport. * @param {boolean} useVisualViewport Whether or not the `window.visualViewport` should be used. - * @returns {Rect} The rectangle of the visual viewport. + * @returns {import('popup').Rect} The rectangle of the visual viewport. */ _getViewport(useVisualViewport) { - const visualViewport = window.visualViewport; - if (visualViewport !== null && typeof visualViewport === 'object') { + const {visualViewport} = window; + if (typeof visualViewport !== 'undefined' && visualViewport !== null) { const left = visualViewport.offsetLeft; const top = visualViewport.offsetTop; const width = visualViewport.width; @@ -882,6 +997,9 @@ export class Popup extends EventDispatcher { }; } + /** + * @param {import('settings').OptionsContext} optionsContext + */ async _setOptionsContext(optionsContext) { this._optionsContext = optionsContext; const options = await yomitan.api.optionsGet(optionsContext); @@ -902,10 +1020,12 @@ export class Popup extends EventDispatcher { this._useSecureFrameUrl = general.useSecurePopupFrameUrl; this._useShadowDom = general.usePopupShadowDom; this._customOuterCss = general.customPopupOuterCss; - this._optionsAssigned = true; this.updateTheme(); } + /** + * @param {import('settings').OptionsContext} optionsContext + */ async _setOptionsContextIfDifferent(optionsContext) { if (deepEqual(this._optionsContext, optionsContext)) { return; } await this._setOptionsContext(optionsContext); @@ -913,8 +1033,8 @@ export class Popup extends EventDispatcher { /** * Computes the bounding rectangle for a set of rectangles. - * @param {Rect[]} sourceRects An array of rectangles. - * @returns {Rect} The bounding rectangle for all of the source rectangles. + * @param {import('popup').Rect[]} sourceRects An array of rectangles. + * @returns {import('popup').Rect} The bounding rectangle for all of the source rectangles. */ _getBoundingSourceRect(sourceRects) { switch (sourceRects.length) { @@ -934,8 +1054,8 @@ export class Popup extends EventDispatcher { /** * Checks whether or not a rectangle is overlapping any other rectangles. - * @param {SizeRect} sizeRect The rectangles to check for overlaps. - * @param {Rect[]} sourceRects The list of rectangles to compare against. + * @param {import('popup').SizeRect} sizeRect The rectangles to check for overlaps. + * @param {import('popup').Rect[]} sourceRects The list of rectangles to compare against. * @param {number} ignoreIndex The index of an item in `sourceRects` to ignore. * @returns {boolean} `true` if `sizeRect` overlaps any one of `sourceRects`, excluding `sourceRects[ignoreIndex]`; `false` otherwise. */ @@ -968,8 +1088,8 @@ export class Popup extends EventDispatcher { /** * Converts the coordinate space of source rectangles. - * @param {Rect[]} sourceRects The list of rectangles to convert. - * @returns {Rect[]} Either an updated list of rectangles, or `sourceRects` if no change is required. + * @param {import('popup').Rect[]} sourceRects The list of rectangles to convert. + * @returns {import('popup').Rect[]} Either an updated list of rectangles, or `sourceRects` if no change is required. */ _convertSourceRectsCoordinateSpace(sourceRects) { let scale = DocumentUtil.computeZoomScale(this._container); @@ -984,9 +1104,9 @@ export class Popup extends EventDispatcher { /** * Creates a scaled rectangle. - * @param {Rect} rect The rectangle to scale. + * @param {import('popup').Rect} rect The rectangle to scale. * @param {number} scale The scale factor. - * @returns {Rect} A new rectangle which has been scaled. + * @returns {import('popup').Rect} A new rectangle which has been scaled. */ _createScaledRect(rect, scale) { return { @@ -997,3 +1117,18 @@ export class Popup extends EventDispatcher { }; } } + +class PopupError extends ExtensionError { + /** + * @param {string} message + * @param {Popup} source + */ + constructor(message, source) { + super(message); + /** @type {Popup} */ + this._source = source; + } + + /** @type {Popup} */ + get source() { return this._source; } +} -- cgit v1.2.3 From 6a3dae04de68ab633da15bbc8ec6b350e38e6d2f Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 13:54:43 -0500 Subject: Add extension error imports --- ext/js/app/popup.js | 1 + ext/js/comm/anki-connect.js | 1 + ext/js/data/anki-note-builder.js | 1 + ext/js/display/display-generator.js | 1 + ext/js/display/option-toggle-hotkey-handler.js | 1 + ext/js/language/dictionary-worker-handler.js | 1 + ext/js/language/dictionary-worker-media-loader.js | 1 + ext/js/language/dictionary-worker.js | 1 + ext/js/media/audio-downloader.js | 1 + ext/js/pages/settings/anki-controller.js | 1 + ext/js/pages/settings/anki-templates-controller.js | 1 + ext/js/pages/settings/dictionary-import-controller.js | 1 + ext/js/pages/settings/generic-setting-controller.js | 1 + ext/js/templates/sandbox/template-renderer-frame-api.js | 2 ++ ext/js/templates/sandbox/template-renderer.js | 1 + ext/js/templates/template-renderer-proxy.js | 1 + 16 files changed, 17 insertions(+) (limited to 'ext/js/app/popup.js') diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js index 31b18f01..4f201fc3 100644 --- a/ext/js/app/popup.js +++ b/ext/js/app/popup.js @@ -18,6 +18,7 @@ import {FrameClient} from '../comm/frame-client.js'; import {DynamicProperty, EventDispatcher, EventListenerCollection, deepEqual} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {DocumentUtil} from '../dom/document-util.js'; import {dynamicLoader} from '../script/dynamic-loader.js'; import {yomitan} from '../yomitan.js'; diff --git a/ext/js/comm/anki-connect.js b/ext/js/comm/anki-connect.js index b876703f..7ff8d0e1 100644 --- a/ext/js/comm/anki-connect.js +++ b/ext/js/comm/anki-connect.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {AnkiUtil} from '../data/anki-util.js'; /** diff --git a/ext/js/data/anki-note-builder.js b/ext/js/data/anki-note-builder.js index f8296ee0..28809e1f 100644 --- a/ext/js/data/anki-note-builder.js +++ b/ext/js/data/anki-note-builder.js @@ -17,6 +17,7 @@ */ import {deferPromise} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {TemplateRendererProxy} from '../templates/template-renderer-proxy.js'; import {yomitan} from '../yomitan.js'; import {AnkiUtil} from './anki-util.js'; diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index 9fc700f3..e8be79d9 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -17,6 +17,7 @@ */ import {isObject} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {HtmlTemplateCollection} from '../dom/html-template-collection.js'; import {DictionaryDataUtil} from '../language/sandbox/dictionary-data-util.js'; import {yomitan} from '../yomitan.js'; diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js index e73fcf04..9677e86b 100644 --- a/ext/js/display/option-toggle-hotkey-handler.js +++ b/ext/js/display/option-toggle-hotkey-handler.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {yomitan} from '../yomitan.js'; export class OptionToggleHotkeyHandler { diff --git a/ext/js/language/dictionary-worker-handler.js b/ext/js/language/dictionary-worker-handler.js index 3a85cb71..9a724386 100644 --- a/ext/js/language/dictionary-worker-handler.js +++ b/ext/js/language/dictionary-worker-handler.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {DictionaryDatabase} from './dictionary-database.js'; import {DictionaryImporter} from './dictionary-importer.js'; import {DictionaryWorkerMediaLoader} from './dictionary-worker-media-loader.js'; diff --git a/ext/js/language/dictionary-worker-media-loader.js b/ext/js/language/dictionary-worker-media-loader.js index 2701389e..e19a13d3 100644 --- a/ext/js/language/dictionary-worker-media-loader.js +++ b/ext/js/language/dictionary-worker-media-loader.js @@ -17,6 +17,7 @@ */ import {generateId} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; /** * Class used for loading and validating media from a worker thread diff --git a/ext/js/language/dictionary-worker.js b/ext/js/language/dictionary-worker.js index b9d0236c..3e78a6ff 100644 --- a/ext/js/language/dictionary-worker.js +++ b/ext/js/language/dictionary-worker.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {DictionaryImporterMediaLoader} from './dictionary-importer-media-loader.js'; export class DictionaryWorker { diff --git a/ext/js/media/audio-downloader.js b/ext/js/media/audio-downloader.js index 8bd04b2b..7b236790 100644 --- a/ext/js/media/audio-downloader.js +++ b/ext/js/media/audio-downloader.js @@ -17,6 +17,7 @@ */ import {RequestBuilder} from '../background/request-builder.js'; +import {ExtensionError} from '../core/extension-error.js'; import {JsonSchema} from '../data/json-schema.js'; import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; import {NativeSimpleDOMParser} from '../dom/native-simple-dom-parser.js'; diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js index 0ccd018d..722459df 100644 --- a/ext/js/pages/settings/anki-controller.js +++ b/ext/js/pages/settings/anki-controller.js @@ -18,6 +18,7 @@ import {AnkiConnect} from '../../comm/anki-connect.js'; import {EventListenerCollection, log} from '../../core.js'; +import {ExtensionError} from '../../core/extension-error.js'; import {AnkiUtil} from '../../data/anki-util.js'; import {SelectorObserver} from '../../dom/selector-observer.js'; import {ObjectPropertyAccessor} from '../../general/object-property-accessor.js'; diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js index d2814880..a0ff96b2 100644 --- a/ext/js/pages/settings/anki-templates-controller.js +++ b/ext/js/pages/settings/anki-templates-controller.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../../core/extension-error.js'; import {AnkiNoteBuilder} from '../../data/anki-note-builder.js'; import {JapaneseUtil} from '../../language/sandbox/japanese-util.js'; import {yomitan} from '../../yomitan.js'; diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js index 106ecbca..af8c2fcd 100644 --- a/ext/js/pages/settings/dictionary-import-controller.js +++ b/ext/js/pages/settings/dictionary-import-controller.js @@ -17,6 +17,7 @@ */ import {log} from '../../core.js'; +import {ExtensionError} from '../../core/extension-error.js'; import {DictionaryWorker} from '../../language/dictionary-worker.js'; import {yomitan} from '../../yomitan.js'; import {DictionaryController} from './dictionary-controller.js'; diff --git a/ext/js/pages/settings/generic-setting-controller.js b/ext/js/pages/settings/generic-setting-controller.js index 3c6104a9..47c0d6fe 100644 --- a/ext/js/pages/settings/generic-setting-controller.js +++ b/ext/js/pages/settings/generic-setting-controller.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../../core/extension-error.js'; import {DocumentUtil} from '../../dom/document-util.js'; import {DOMDataBinder} from '../../dom/dom-data-binder.js'; diff --git a/ext/js/templates/sandbox/template-renderer-frame-api.js b/ext/js/templates/sandbox/template-renderer-frame-api.js index 31ba4500..91400ab8 100644 --- a/ext/js/templates/sandbox/template-renderer-frame-api.js +++ b/ext/js/templates/sandbox/template-renderer-frame-api.js @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../../core/extension-error.js'; + export class TemplateRendererFrameApi { /** * @param {TemplateRenderer} templateRenderer diff --git a/ext/js/templates/sandbox/template-renderer.js b/ext/js/templates/sandbox/template-renderer.js index c7613533..716e3ccc 100644 --- a/ext/js/templates/sandbox/template-renderer.js +++ b/ext/js/templates/sandbox/template-renderer.js @@ -17,6 +17,7 @@ */ import {Handlebars} from '../../../lib/handlebars.js'; +import {ExtensionError} from '../../core/extension-error.js'; export class TemplateRenderer { constructor() { diff --git a/ext/js/templates/template-renderer-proxy.js b/ext/js/templates/template-renderer-proxy.js index e67b715a..642eea8b 100644 --- a/ext/js/templates/template-renderer-proxy.js +++ b/ext/js/templates/template-renderer-proxy.js @@ -17,6 +17,7 @@ */ import {generateId} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; export class TemplateRendererProxy { constructor() { -- cgit v1.2.3 From dcddbee07e20163ae167dd67fe58f0776f9acb64 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Dec 2023 18:20:05 -0500 Subject: Update how ts comments are handled --- .eslintrc.json | 9 ++++++++- dev/translator-vm.js | 2 +- ext/js/accessibility/google-docs.js | 6 +++--- ext/js/app/popup.js | 2 +- ext/js/background/offscreen-proxy.js | 8 ++++---- ext/js/comm/frame-ancestry-handler.js | 4 ++-- ext/js/dom/document-util.js | 14 ++++++------- ext/js/dom/dom-text-scanner.js | 5 ++--- ext/js/dom/simple-dom-parser.js | 3 +-- ext/js/pages/settings/backup-controller.js | 4 ++-- ext/js/yomitan.js | 4 ++-- test/cache-map.test.js | 2 +- test/data/html/test-document2-script.js | 30 ++++++++++++++-------------- test/object-property-accessor.test.js | 6 +++--- test/profile-conditions-util.test.js | 32 +++++++++++++++--------------- vitest.config.js | 2 +- 16 files changed, 69 insertions(+), 64 deletions(-) (limited to 'ext/js/app/popup.js') diff --git a/.eslintrc.json b/.eslintrc.json index a46aff4b..83e7ffe6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -350,7 +350,14 @@ "allowAllPropertiesOnSameLine": true } ], - "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-expect-error": { + "descriptionFormat": "^ - .+$" + } + } + ], "@typescript-eslint/ban-types": [ "error", { diff --git a/dev/translator-vm.js b/dev/translator-vm.js index 4022d465..7fdda879 100644 --- a/dev/translator-vm.js +++ b/dev/translator-vm.js @@ -42,7 +42,7 @@ export class TranslatorVM { } } }; - // @ts-ignore - Overwriting a global + // @ts-expect-error - Overwriting a global global.chrome = chrome; /** @type {?JapaneseUtil} */ diff --git a/ext/js/accessibility/google-docs.js b/ext/js/accessibility/google-docs.js index da6ab994..27841b6d 100644 --- a/ext/js/accessibility/google-docs.js +++ b/ext/js/accessibility/google-docs.js @@ -18,9 +18,9 @@ (async () => { // Reentrant check - // @ts-ignore : Checking a property to the global object + // @ts-expect-error - Checking a property to the global object if (self.googleDocsAccessibilitySetup) { return; } - // @ts-ignore : Adding a property to the global object + // @ts-expect-error - Adding a property to the global object self.googleDocsAccessibilitySetup = true; /** @@ -57,7 +57,7 @@ // The extension ID below is on an allow-list that is used on the Google Docs webpage. /* eslint-disable */ - // @ts-ignore : Adding a property to the global object + // @ts-expect-error : Adding a property to the global object const inject = () => { window._docs_annotate_canvas_by_ext = 'ogmnaimimemjmbakcfefmnahgdfhfami'; }; /* eslint-enable */ diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js index 4f201fc3..7419785b 100644 --- a/ext/js/app/popup.js +++ b/ext/js/app/popup.js @@ -745,7 +745,7 @@ export class Popup extends EventDispatcher { if ( fullscreenElement === null || fullscreenElement.shadowRoot || - // @ts-ignore - openOrClosedShadowRoot is available to Firefox 63+ for WebExtensions + // @ts-expect-error - openOrClosedShadowRoot is available to Firefox 63+ for WebExtensions fullscreenElement.openOrClosedShadowRoot ) { return defaultParent; diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js index 7b504855..63f619fa 100644 --- a/ext/js/background/offscreen-proxy.js +++ b/ext/js/background/offscreen-proxy.js @@ -54,16 +54,16 @@ export class OffscreenProxy { */ async _hasOffscreenDocument() { const offscreenUrl = chrome.runtime.getURL('offscreen.html'); - // @ts-ignore - API not defined yet + // @ts-expect-error - API not defined yet if (!chrome.runtime.getContexts) { // chrome version below 116 // Clients: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/clients - // @ts-ignore - Types not set up for service workers yet + // @ts-expect-error - Types not set up for service workers yet const matchedClients = await clients.matchAll(); - // @ts-ignore - Types not set up for service workers yet + // @ts-expect-error - Types not set up for service workers yet return await matchedClients.some((client) => client.url === offscreenUrl); } - // @ts-ignore - API not defined yet + // @ts-expect-error - API not defined yet const contexts = await chrome.runtime.getContexts({ contextTypes: ['OFFSCREEN_DOCUMENT'], documentUrls: [offscreenUrl] diff --git a/ext/js/comm/frame-ancestry-handler.js b/ext/js/comm/frame-ancestry-handler.js index 687ec368..e4d08f28 100644 --- a/ext/js/comm/frame-ancestry-handler.js +++ b/ext/js/comm/frame-ancestry-handler.js @@ -295,7 +295,7 @@ export class FrameAncestryHandler { while (walker.nextNode()) { const element = /** @type {Element} */ (walker.currentNode); - // @ts-ignore - this is more simple to elide any type checks or casting + // @ts-expect-error - this is more simple to elide any type checks or casting if (element.contentWindow === contentWindow) { return element; } @@ -303,7 +303,7 @@ export class FrameAncestryHandler { /** @type {?ShadowRoot|undefined} */ const shadowRoot = ( element.shadowRoot || - // @ts-ignore - openOrClosedShadowRoot is available to Firefox 63+ for WebExtensions + // @ts-expect-error - openOrClosedShadowRoot is available to Firefox 63+ for WebExtensions element.openOrClosedShadowRoot ); if (shadowRoot) { diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js index 549a8195..b2aa8f81 100644 --- a/ext/js/dom/document-util.js +++ b/ext/js/dom/document-util.js @@ -210,7 +210,7 @@ export class DocumentUtil { */ static computeZoomScale(node) { if (this._cssZoomSupported === null) { - // @ts-ignore - zoom is a non-standard property that exists in Chromium-based browsers + // @ts-expect-error - zoom is a non-standard property that exists in Chromium-based browsers this._cssZoomSupported = (typeof document.createElement('div').style.zoom === 'string'); } if (!this._cssZoomSupported) { return 1; } @@ -387,11 +387,11 @@ export class DocumentUtil { static getFullscreenElement() { return ( document.fullscreenElement || - // @ts-ignore - vendor prefix + // @ts-expect-error - vendor prefix document.msFullscreenElement || - // @ts-ignore - vendor prefix + // @ts-expect-error - vendor prefix document.mozFullScreenElement || - // @ts-ignore - vendor prefix + // @ts-expect-error - vendor prefix document.webkitFullscreenElement || null ); @@ -808,7 +808,7 @@ export class DocumentUtil { return document.caretRangeFromPoint(x, y); } - // @ts-ignore - caretPositionFromPoint is non-standard + // @ts-expect-error - caretPositionFromPoint is non-standard if (typeof document.caretPositionFromPoint === 'function') { // Firefox return this._caretPositionFromPoint(x, y); @@ -824,7 +824,7 @@ export class DocumentUtil { * @returns {?Range} */ static _caretPositionFromPoint(x, y) { - // @ts-ignore - caretPositionFromPoint is non-standard + // @ts-expect-error - caretPositionFromPoint is non-standard const position = /** @type {(x: number, y: number) => ?{offsetNode: Node, offset: number}} */ (document.caretPositionFromPoint)(x, y); if (position === null) { return null; @@ -876,7 +876,7 @@ export class DocumentUtil { nextElement.style.setProperty('user-select', 'text', 'important'); } - // @ts-ignore - caretPositionFromPoint is non-standard + // @ts-expect-error - caretPositionFromPoint is non-standard const position = /** @type {(x: number, y: number) => ?{offsetNode: Node, offset: number}} */ (document.caretPositionFromPoint)(x, y); if (position === null) { return null; diff --git a/ext/js/dom/dom-text-scanner.js b/ext/js/dom/dom-text-scanner.js index 3a785680..42e0acc9 100644 --- a/ext/js/dom/dom-text-scanner.js +++ b/ext/js/dom/dom-text-scanner.js @@ -520,11 +520,10 @@ export class DOMTextScanner { static isStyleSelectable(style) { return !( style.userSelect === 'none' || - // @ts-ignore - vendor prefix style.webkitUserSelect === 'none' || - // @ts-ignore - vendor prefix + // @ts-expect-error - vendor prefix style.MozUserSelect === 'none' || - // @ts-ignore - vendor prefix + // @ts-expect-error - vendor prefix style.msUserSelect === 'none' ); } diff --git a/ext/js/dom/simple-dom-parser.js b/ext/js/dom/simple-dom-parser.js index a1f63890..bca1cd88 100644 --- a/ext/js/dom/simple-dom-parser.js +++ b/ext/js/dom/simple-dom-parser.js @@ -27,7 +27,7 @@ export class SimpleDOMParser { */ constructor(content) { /** @type {import('parse5')} */ - // @ts-ignore - parse5 global is not defined in typescript declaration + // @ts-expect-error - parse5 global is not defined in typescript declaration this._parse5Lib = /** @type {import('parse5')} */ (parse5); /** @type {import('parse5').TreeAdapter} */ this._treeAdapter = this._parse5Lib.defaultTreeAdapter; @@ -131,7 +131,6 @@ export class SimpleDOMParser { * @returns {boolean} */ static isSupported() { - // @ts-ignore - parse5 global is not defined in typescript declaration return typeof parse5 !== 'undefined'; } diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js index 52c5f418..bf44bb90 100644 --- a/ext/js/pages/settings/backup-controller.js +++ b/ext/js/pages/settings/backup-controller.js @@ -165,9 +165,9 @@ export class BackupController { _saveBlob(blob, fileName) { if ( typeof navigator === 'object' && navigator !== null && - // @ts-ignore - call for legacy Edge + // @ts-expect-error - call for legacy Edge typeof navigator.msSaveBlob === 'function' && - // @ts-ignore - call for legacy Edge + // @ts-expect-error - call for legacy Edge navigator.msSaveBlob(blob) ) { return; diff --git a/ext/js/yomitan.js b/ext/js/yomitan.js index 3c0f7cb9..7cf67aec 100644 --- a/ext/js/yomitan.js +++ b/ext/js/yomitan.js @@ -37,7 +37,7 @@ if ((() => { } return (hasBrowser && !hasChrome); })()) { - // @ts-ignore - objects should have roughly the same interface + // @ts-expect-error - objects should have roughly the same interface chrome = browser; } @@ -182,7 +182,7 @@ export class Yomitan extends EventDispatcher { */ sendMessage(...args) { try { - // @ts-ignore - issue with type conversion, somewhat difficult to resolve in pure JS + // @ts-expect-error - issue with type conversion, somewhat difficult to resolve in pure JS chrome.runtime.sendMessage(...args); } catch (e) { this.triggerExtensionUnloaded(); diff --git a/test/cache-map.test.js b/test/cache-map.test.js index 3e7def1f..df891188 100644 --- a/test/cache-map.test.js +++ b/test/cache-map.test.js @@ -30,7 +30,7 @@ function testConstructor() { [true, () => new CacheMap(1.5)], [true, () => new CacheMap(Number.NaN)], [true, () => new CacheMap(Number.POSITIVE_INFINITY)], - // @ts-ignore - Ignore because it should throw an error + // @ts-expect-error - Ignore because it should throw an error [true, () => new CacheMap('a')] ]; diff --git a/test/data/html/test-document2-script.js b/test/data/html/test-document2-script.js index 5a6ad4d1..f6082802 100644 --- a/test/data/html/test-document2-script.js +++ b/test/data/html/test-document2-script.js @@ -22,17 +22,17 @@ function requestFullscreen(element) { if (element.requestFullscreen) { element.requestFullscreen(); - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility } else if (element.mozRequestFullScreen) { - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility element.mozRequestFullScreen(); - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility } else if (element.webkitRequestFullscreen) { - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility element.webkitRequestFullscreen(); - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility } else if (element.msRequestFullscreen) { - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility element.msRequestFullscreen(); } } @@ -41,17 +41,17 @@ function requestFullscreen(element) { function exitFullscreen() { if (document.exitFullscreen) { document.exitFullscreen(); - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility } else if (document.mozCancelFullScreen) { - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility document.mozCancelFullScreen(); - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility } else if (document.webkitExitFullscreen) { - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility document.webkitExitFullscreen(); - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility } else if (document.msExitFullscreen) { - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility document.msExitFullscreen(); } } @@ -62,11 +62,11 @@ function exitFullscreen() { function getFullscreenElement() { return ( document.fullscreenElement || - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility document.msFullscreenElement || - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility document.mozFullScreenElement || - // @ts-ignore - Browser compatibility + // @ts-expect-error - Browser compatibility document.webkitFullscreenElement || null ); diff --git a/test/object-property-accessor.test.js b/test/object-property-accessor.test.js index 4f1fa87b..4d50b1e9 100644 --- a/test/object-property-accessor.test.js +++ b/test/object-property-accessor.test.js @@ -334,7 +334,7 @@ function testGetPathString2() { ]; for (const [pathArray, message] of data) { - // @ts-ignore - Throwing is expected + // @ts-expect-error - Throwing is expected expect(() => ObjectPropertyAccessor.getPathString(pathArray)).toThrow(message); } }); @@ -424,7 +424,7 @@ function testHasProperty() { ]; for (const [object, property, expected] of data) { - // @ts-ignore - Ignore potentially property types + // @ts-expect-error - Ignore potentially property types expect(ObjectPropertyAccessor.hasProperty(object, property)).toStrictEqual(expected); } }); @@ -449,7 +449,7 @@ function testIsValidPropertyType() { ]; for (const [object, property, expected] of data) { - // @ts-ignore - Ignore potentially property types + // @ts-expect-error - Ignore potentially property types expect(ObjectPropertyAccessor.isValidPropertyType(object, property)).toStrictEqual(expected); } }); diff --git a/test/profile-conditions-util.test.js b/test/profile-conditions-util.test.js index 30052b34..62b21555 100644 --- a/test/profile-conditions-util.test.js +++ b/test/profile-conditions-util.test.js @@ -637,9 +637,9 @@ function testSchemas() { {expected: true, context: {depth: 0, url: ''}}, {expected: true, context: {depth: 0, url: '', flags: []}}, {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -673,9 +673,9 @@ function testSchemas() { {expected: false, context: {depth: 0, url: ''}}, {expected: false, context: {depth: 0, url: '', flags: []}}, {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -711,9 +711,9 @@ function testSchemas() { {expected: false, context: {depth: 0, url: ''}}, {expected: false, context: {depth: 0, url: '', flags: []}}, {expected: true, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -753,9 +753,9 @@ function testSchemas() { {expected: true, context: {depth: 0, url: ''}}, {expected: true, context: {depth: 0, url: '', flags: []}}, {expected: true, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -784,9 +784,9 @@ function testSchemas() { {expected: true, context: {depth: 0, url: ''}}, {expected: true, context: {depth: 0, url: '', flags: []}}, {expected: true, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -819,9 +819,9 @@ function testSchemas() { {expected: false, context: {depth: 0, url: ''}}, {expected: false, context: {depth: 0, url: '', flags: []}}, {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -849,9 +849,9 @@ function testSchemas() { {expected: true, context: {depth: 0, url: ''}}, {expected: true, context: {depth: 0, url: '', flags: []}}, {expected: true, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: true, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, @@ -885,9 +885,9 @@ function testSchemas() { {expected: true, context: {depth: 0, url: ''}}, {expected: true, context: {depth: 0, url: '', flags: []}}, {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, - // @ts-ignore - Ignore type for string flag for testing purposes + // @ts-expect-error - Ignore type for string flag for testing purposes {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}} ] }, diff --git a/vitest.config.js b/vitest.config.js index 3b6cdde0..025eec17 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -24,7 +24,7 @@ export default defineConfig({ 'test/playwright/**' ], environment: 'jsdom', - // @ts-ignore - Appears to not be defined in the type definitions (https://vitest.dev/advanced/pool) + // @ts-expect-error - Appears to not be defined in the type definitions (https://vitest.dev/advanced/pool) poolOptions: { threads: { useAtomics: true -- cgit v1.2.3