diff --git a/README.md b/README.md index 05b48b34..a0fca4a7 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - [Routines](#5-routines) - [Live](#live) - [Adapter API](#adapter-api) +- [Compile-Time Logging Control](#compile-time-logging-control) - [Thanks](#thanks) ## Overview @@ -279,6 +280,30 @@ console.log('The Workflow runs'); // 1st output VScroll will receive its own Adapter API documentation later, but for now please refer to [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll#adapter-api). +## Compile-Time Logging Control + +`vscroll` includes detailed internal logging useful for debugging. To avoid unnecessary overhead in production, you can disable logging at compile time by defining a global constant: + +```js +// webpack.config.js +new webpack.DefinePlugin({ + vscroll_enableLogging: JSON.stringify(false) +}); +``` + +Or when using ESBuild: + +```js +import { build } from 'esbuild'; + +build({ + ..., + define: { + vscroll_enableLogging: JSON.stringify(false) + } +}); +``` + ## Thanks \- to [Mike Feingold](https://github.com/mfeingold) as he started all this story in far 2013, diff --git a/src/classes/adapter.ts b/src/classes/adapter.ts index b6f99187..15ab6a34 100644 --- a/src/classes/adapter.ts +++ b/src/classes/adapter.ts @@ -132,11 +132,15 @@ export class Adapter implements IAdapter { private getWorkflowRunnerMethod(method: MethodResolver, name: AdapterPropName) { return (...args: unknown[]): Promise => { if (!this.relax$) { - this.logger?.log?.(() => 'scroller is not initialized: ' + name + ' method is ignored'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger?.log?.(() => 'scroller is not initialized: ' + name + ' method is ignored'); + } return Promise.resolve(methodPreResult); } if (this.paused && !ALLOWED_METHODS_WHEN_PAUSED.includes(name)) { - this.logger?.log?.(() => 'scroller is paused: ' + name + ' method is ignored'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger?.log?.(() => 'scroller is paused: ' + name + ' method is ignored'); + } return Promise.resolve(methodPausedResult); } @@ -337,7 +341,9 @@ export class Adapter implements IAdapter { return; } if (buffer.items.some(({ element }) => !element)) { - logger.log('skipping first/lastVisible set because not all buffered items are rendered at this moment'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log('skipping first/lastVisible set because not all buffered items are rendered at this moment'); + } return; } const direction = first ? Direction.backward : Direction.forward; @@ -423,7 +429,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any reset(options?: IDatasourceOptional): any { this.reloadCounter++; - this.logger.logAdapterMethod('reset', options, ` of ${this.reloadId}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('reset', options, ` of ${this.reloadId}`); + } this.workflow.call({ process: AdapterProcess.reset, status: ProcessStatus.start, @@ -434,7 +442,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any reload(options?: number | string): any { this.reloadCounter++; - this.logger.logAdapterMethod('reload', options, ` of ${this.reloadId}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('reload', options, ` of ${this.reloadId}`); + } this.workflow.call({ process: AdapterProcess.reload, status: ProcessStatus.start, @@ -445,7 +455,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any append(_options: AdapterAppendOptions | unknown, eof?: boolean): any { const options = convertAppendArgs(false, _options, eof); // support old signature - this.logger.logAdapterMethod('append', [options.items, options.eof]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('append', [options.items, options.eof]); + } this.workflow.call({ process: AdapterProcess.append, status: ProcessStatus.start, @@ -456,7 +468,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any prepend(_options: AdapterPrependOptions | unknown, bof?: boolean): any { const options = convertAppendArgs(true, _options, bof); // support old signature - this.logger.logAdapterMethod('prepend', [options.items, options.bof]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('prepend', [options.items, options.bof]); + } this.workflow.call({ process: AdapterProcess.prepend, status: ProcessStatus.start, @@ -466,7 +480,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any check(): any { - this.logger.logAdapterMethod('check'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('check'); + } this.workflow.call({ process: AdapterProcess.check, status: ProcessStatus.start @@ -476,7 +492,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any remove(options: AdapterRemoveOptions | ItemsPredicate): any { options = convertRemoveArgs(options); // support old signature - this.logger.logAdapterMethod('remove', options); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('remove', options); + } this.workflow.call({ process: AdapterProcess.remove, status: ProcessStatus.start, @@ -486,7 +504,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any clip(options?: AdapterClipOptions): any { - this.logger.logAdapterMethod('clip', options); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('clip', options); + } this.workflow.call({ process: AdapterProcess.clip, status: ProcessStatus.start, @@ -496,7 +516,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any insert(options: AdapterInsertOptions): any { - this.logger.logAdapterMethod('insert', options); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('insert', options); + } this.workflow.call({ process: AdapterProcess.insert, status: ProcessStatus.start, @@ -506,7 +528,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any replace(options: AdapterReplaceOptions): any { - this.logger.logAdapterMethod('replace', options); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('replace', options); + } this.workflow.call({ process: AdapterProcess.replace, status: ProcessStatus.start, @@ -516,7 +540,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any update(options: AdapterUpdateOptions): any { - this.logger.logAdapterMethod('update', options); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('update', options); + } this.workflow.call({ process: AdapterProcess.update, status: ProcessStatus.start, @@ -526,7 +552,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any pause(): any { - this.logger.logAdapterMethod('pause'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('pause'); + } this.workflow.call({ process: AdapterProcess.pause, status: ProcessStatus.start @@ -535,7 +563,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any resume(): any { - this.logger.logAdapterMethod('resume'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('resume'); + } this.workflow.call({ process: AdapterProcess.pause, status: ProcessStatus.start, @@ -545,7 +575,9 @@ export class Adapter implements IAdapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any fix(options: AdapterFixOptions): any { - this.logger.logAdapterMethod('fix', options); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('fix', options); + } this.workflow.call({ process: AdapterProcess.fix, status: ProcessStatus.start, @@ -576,7 +608,9 @@ export class Adapter implements IAdapter { }; } const success = reloadId === this.reloadId; - this.logger?.log?.(() => !success ? `relax promise cancelled due to ${reloadId} != ${this.reloadId}` : void 0); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger?.log?.(() => !success ? `relax promise cancelled due to ${reloadId} != ${this.reloadId}` : void 0); + } return { immediate, success, @@ -587,7 +621,9 @@ export class Adapter implements IAdapter { relax(callback?: () => void): Promise { const reloadId = this.reloadId; - this.logger.logAdapterMethod('relax', callback, ` of ${reloadId}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('relax', callback, ` of ${reloadId}`); + } if (!this.init) { return Promise.resolve(methodPreResult); } @@ -600,7 +636,9 @@ export class Adapter implements IAdapter { } showLog(): void { - this.logger.logAdapterMethod('showLog'); - this.logger.logForce(); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.logAdapterMethod('showLog'); + this.logger.logForce(); + } } } diff --git a/src/classes/buffer.ts b/src/classes/buffer.ts index 850c0e31..80e09f5b 100644 --- a/src/classes/buffer.ts +++ b/src/classes/buffer.ts @@ -65,15 +65,21 @@ export class Buffer { const start = this.startIndexUser; let index = Number(newStartIndex); if (Number.isNaN(index)) { - this.logger.log(() => `fallback startIndex to settings.startIndex (${start})`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => `fallback startIndex to settings.startIndex (${start})`); + } index = start; } if (index < min) { - this.logger.log(() => `setting startIndex to settings.minIndex (${min}) because ${index} < ${min}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => `setting startIndex to settings.minIndex (${min}) because ${index} < ${min}`); + } index = min; } if (index > max) { - this.logger.log(() => `setting startIndex to settings.maxIndex (${max}) because ${index} > ${max}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => `setting startIndex to settings.maxIndex (${max}) because ${index} > ${max}`); + } index = max; } this.startIndex = index; diff --git a/src/classes/buffer/cache.ts b/src/classes/buffer/cache.ts index cd5a78b9..2d7dbd02 100644 --- a/src/classes/buffer/cache.ts +++ b/src/classes/buffer/cache.ts @@ -85,7 +85,9 @@ export class Cache { recalculateDefaultSize(): boolean { if (this.defaultSize.recalculate(this.size)) { - this.logger.log(() => `default size has been updated: ${this.defaultSize.get()}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => `default size has been updated: ${this.defaultSize.get()}`); + } return true; } return false; diff --git a/src/classes/buffer/checkCall.ts b/src/classes/buffer/checkCall.ts index 695a3fc1..ff3d7400 100644 --- a/src/classes/buffer/checkCall.ts +++ b/src/classes/buffer/checkCall.ts @@ -14,14 +14,20 @@ export class CheckBufferCall { fillEmpty(items: Data[], before?: number, after?: number): boolean { if (!items.length) { - this.logger.log('no items to fill the buffer; empty list'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log('no items to fill the buffer; empty list'); + } return false; } if (!Number.isInteger(before) && !Number.isInteger(after)) { - this.logger.log('no items to fill the buffer; wrong indexes'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log('no items to fill the buffer; wrong indexes'); + } return false; } - this.logger.log(() => `going to fill the buffer with ${items.length} item(s)`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => `going to fill the buffer with ${items.length} item(s)`); + } return true; } @@ -32,7 +38,9 @@ export class CheckBufferCall { (Number.isInteger(index) && index === item.$index) ); if (!found) { - this.logger.log('no items to insert in buffer; empty predicate\'s result'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log('no items to insert in buffer; empty predicate\'s result'); + } return NaN; } return found.$index; @@ -40,25 +48,33 @@ export class CheckBufferCall { insertVirtual(items: Data[], index: number, direction: Direction): boolean { if (!items.length) { - this.logger.log('no items to insert virtually; empty list'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log('no items to insert virtually; empty list'); + } return false; } const { firstIndex, lastIndex, finiteAbsMinIndex, finiteAbsMaxIndex } = this.context; if (index < finiteAbsMinIndex || index > finiteAbsMaxIndex) { - this.logger.log(() => - 'no items to insert virtually; ' + - `selected index (${index}) does not match virtual area [${finiteAbsMinIndex}..${finiteAbsMaxIndex}]` - ); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => + 'no items to insert virtually; ' + + `selected index (${index}) does not match virtual area [${finiteAbsMinIndex}..${finiteAbsMaxIndex}]` + ); + } return false; } const before = direction === Direction.backward; if (!(index < firstIndex + (before ? 1 : 0) || index > lastIndex - (before ? 0 : 1))) { - this.logger.log(() => - `no items to insert virtually; selected index (${index}) belongs Buffer [${firstIndex}..${lastIndex}]` - ); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => + `no items to insert virtually; selected index (${index}) belongs Buffer [${firstIndex}..${lastIndex}]` + ); + } return false; } - this.logger.log(() => `going to insert ${items.length} item(s) virtually`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => `going to insert ${items.length} item(s) virtually`); + } return true; } diff --git a/src/classes/viewport.ts b/src/classes/viewport.ts index b9d75ad7..19930d60 100644 --- a/src/classes/viewport.ts +++ b/src/classes/viewport.ts @@ -34,14 +34,18 @@ export class Viewport { setPosition(value: number): number { const oldPosition = this.scrollPosition; if (oldPosition === value) { - this.logger.log(() => ['setting scroll position at', value, '[cancelled]']); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => ['setting scroll position at', value, '[cancelled]']); + } return value; } this.routines.setScrollPosition(value); const position = this.scrollPosition; - this.logger.log(() => [ - 'setting scroll position at', position, ...(position !== value ? [`(${value})`] : []) - ]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => [ + 'setting scroll position at', position, ...(position !== value ? [`(${value})`] : []) + ]); + } return position; } diff --git a/src/global-defs.ts b/src/global-defs.ts new file mode 100644 index 00000000..986f8efa --- /dev/null +++ b/src/global-defs.ts @@ -0,0 +1,5 @@ +declare global { + const vscroll_enableLogging: boolean; +} + +export default {}; diff --git a/src/index.ts b/src/index.ts index 6506f441..587122c6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +import './global-defs'; + import { Workflow } from './workflow'; import { makeDatasource } from './classes/datasource'; import { Routines } from './classes/domRoutines'; diff --git a/src/processes/adapter/check.ts b/src/processes/adapter/check.ts index 6ac99979..3d3ca631 100644 --- a/src/processes/adapter/check.ts +++ b/src/processes/adapter/check.ts @@ -31,7 +31,9 @@ export default class Check extends BaseAdapterProcessFactory(AdapterProcess.chec ); } - scroller.logger.stat('check'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.stat('check'); + } workflow.call({ process: Check.process, diff --git a/src/processes/adapter/fix.ts b/src/processes/adapter/fix.ts index 04c56cad..2c1a8fe5 100644 --- a/src/processes/adapter/fix.ts +++ b/src/processes/adapter/fix.ts @@ -79,7 +79,9 @@ export default class Fix extends BaseAdapterProcessFactory(AdapterProcess.fix) { const updater = () => updateReference = true; buffer.items.forEach(item => value(item.get(), updater)); if (updateReference) { - logger.log(() => 'update Buffer.items reference'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => 'update Buffer.items reference'); + } buffer.items = [...buffer.items]; } } @@ -87,7 +89,9 @@ export default class Fix extends BaseAdapterProcessFactory(AdapterProcess.fix) { static scrollToItem(scroller: Scroller, value: ItemsPredicate, options?: boolean | ScrollIntoViewOptions): void { const found = scroller.buffer.items.find(item => value(item.get())); if (!found) { - scroller.logger.log(() => 'scrollToItem cancelled, item not found'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => 'scrollToItem cancelled, item not found'); + } return; } found.scrollTo(options); diff --git a/src/processes/adapter/pause.ts b/src/processes/adapter/pause.ts index f37606fe..b46b34f3 100644 --- a/src/processes/adapter/pause.ts +++ b/src/processes/adapter/pause.ts @@ -8,7 +8,9 @@ export default class Pause extends BaseAdapterProcessFactory(AdapterProcess.paus // pause branch if (!resume && !scroller.state.paused.get()) { - scroller.logger.log('pause scroller'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('pause scroller'); + } scroller.state.paused.set(true); scroller.workflow.call({ process: AdapterProcess.pause, @@ -17,7 +19,9 @@ export default class Pause extends BaseAdapterProcessFactory(AdapterProcess.paus return; } - scroller.logger.log('resume scroller'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('resume scroller'); + } scroller.state.paused.set(false); scroller.workflow.call({ process: AdapterProcess.pause, diff --git a/src/processes/adapter/remove.ts b/src/processes/adapter/remove.ts index 56083609..7abef9c7 100644 --- a/src/processes/adapter/remove.ts +++ b/src/processes/adapter/remove.ts @@ -42,7 +42,9 @@ export default class Remove extends BaseAdapterProcessFactory(AdapterProcess.rem if (!shouldBuffered && !shouldVirtual) { return false; } - scroller.logger.stat('after remove'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.stat('after remove'); + } return true; } @@ -101,7 +103,9 @@ export default class Remove extends BaseAdapterProcessFactory(AdapterProcess.rem } // virtual removal - scroller.logger.log(() => `going to remove ${toRemove.length} item(s) virtually`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => `going to remove ${toRemove.length} item(s) virtually`); + } buffer.removeVirtually(toRemove, !!increase); buffer.checkDefaultSize(); Remove.shiftFirstVisibleIndex(scroller, toRemove, !!increase); diff --git a/src/processes/adapter/replace.ts b/src/processes/adapter/replace.ts index 5c9bd8a6..d1f68ae6 100644 --- a/src/processes/adapter/replace.ts +++ b/src/processes/adapter/replace.ts @@ -24,7 +24,9 @@ export default class Replace extends BaseAdapterProcessFactory(AdapterProcess.re .map(item => item.$index); if (!toRemove.length) { - scroller.logger.log('no items to be replaced'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('no items to be replaced'); + } return false; } diff --git a/src/processes/adapter/update.ts b/src/processes/adapter/update.ts index b6fa7035..48f498bd 100644 --- a/src/processes/adapter/update.ts +++ b/src/processes/adapter/update.ts @@ -23,7 +23,9 @@ export default class Update extends BaseAdapterProcessFactory(AdapterProcess.upd static doUpdate(scroller: Scroller, params: AdapterUpdateOptions): boolean { const { buffer, viewport, state: { fetch }, routines, logger } = scroller; if (!buffer.items) { - logger.log(() => 'no items in Buffer'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => 'no items in Buffer'); + } return false; } const { item: firstItem, index: firstIndex, diff: firstItemDiff } = @@ -43,19 +45,23 @@ export default class Update extends BaseAdapterProcessFactory(AdapterProcess.upd } toRemove.forEach(item => item.hide()); - logger.log(() => toRemove.length - ? 'items to remove: [' + toRemove.map(({ $index }) => $index).join(',') + ']' - : 'no items to remove' - ); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => toRemove.length + ? 'items to remove: [' + toRemove.map(({ $index }) => $index).join(',') + ']' + : 'no items to remove' + ); + } if (toRemove.length) { // insertions will be processed on render buffer.checkDefaultSize(); } const toRender = buffer.items.filter(({ toInsert }) => toInsert); - logger.log(() => toRender.length - ? 'items to render: [' + toRender.map(({ $index }) => $index).join(',') + ']' - : 'no items to render' - ); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => toRender.length + ? 'items to render: [' + toRender.map(({ $index }) => $index).join(',') + ']' + : 'no items to render' + ); + } fetch.update(trackedIndex, delta, toRender, toRemove); return !!toRemove.length || !!toRender.length; diff --git a/src/processes/adjust.ts b/src/processes/adjust.ts index 30001fcc..747f185c 100644 --- a/src/processes/adjust.ts +++ b/src/processes/adjust.ts @@ -59,15 +59,19 @@ export default class Adjust extends BaseProcessFactory(CommonProcess.adjust) { } else { fwdSize += viewportSizeDiff; } - scroller.logger.log(() => - inverse ? 'backward' : 'forward' + ` padding will be increased by ${viewportSizeDiff} to fill the viewport` - ); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => + inverse ? 'backward' : 'forward' + ` padding will be increased by ${viewportSizeDiff} to fill the viewport` + ); + } } backward.size = bwdSize; forward.size = fwdSize; - scroller.logger.stat('after paddings adjustments'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.stat('after paddings adjustments'); + } } static calculatePosition(scroller: Scroller): number { @@ -76,7 +80,9 @@ export default class Adjust extends BaseProcessFactory(CommonProcess.adjust) { // increase the position to meet the expectation of the first visible item if (!isNaN(fetch.firstVisible.index) && !isNaN(buffer.firstIndex)) { - scroller.logger.log(`first index = ${fetch.firstVisible.index}, delta = ${fetch.firstVisible.delta}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(`first index = ${fetch.firstVisible.index}, delta = ${fetch.firstVisible.delta}`); + } const shouldCheckPreSizeExpectation = fetch.shouldCheckPreSizeExpectation(buffer.lastIndex); buffer.items.forEach(item => { // 1) shift of the buffered items before the first visible item @@ -99,7 +105,9 @@ export default class Adjust extends BaseProcessFactory(CommonProcess.adjust) { if (scroll.positionBeforeAsync !== null) { const diff = render.positionBefore - scroll.positionBeforeAsync; if (diff !== 0) { - scroller.logger.log(`shift position due to fetch-render difference (${diff})`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(`shift position due to fetch-render difference (${diff})`); + } position += diff; } } @@ -133,7 +141,9 @@ export default class Adjust extends BaseProcessFactory(CommonProcess.adjust) { const shift = Math.min(size, diff); if (shift) { viewport.paddings.forward.size += shift; - scroller.logger.log(`increase fwd padding due to lack of items (${diff} -> ${shift})`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(`increase fwd padding due to lack of items (${diff} -> ${shift})`); + } } } @@ -156,7 +166,9 @@ export default class Adjust extends BaseProcessFactory(CommonProcess.adjust) { } scroll.syntheticFulfill = true; viewport.scrollPosition = position; - scroller.logger.stat('after scroll adjustment' + diffLog); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.stat('after scroll adjustment' + diffLog); + } done(); }); } diff --git a/src/processes/clip.ts b/src/processes/clip.ts index d9877f75..122fa0d4 100644 --- a/src/processes/clip.ts +++ b/src/processes/clip.ts @@ -19,7 +19,9 @@ export default class Clip extends BaseProcessFactory(CommonProcess.clip) { const { buffer, viewport: { paddings }, state: { clip }, logger } = scroller; const size = { [Direction.backward]: 0, [Direction.forward]: 0 }; - logger.stat(`before clip (${++clip.callCount})`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.stat(`before clip (${++clip.callCount})`); + } const itemsToRemove = buffer.items.filter(item => { if (!item.toRemove) { @@ -44,19 +46,21 @@ export default class Clip extends BaseProcessFactory(CommonProcess.clip) { buffer.clip(); - logger.log(() => { - const list = itemsToRemove.map(({ $index }) => $index); - return list.length - ? [ - `clipped ${list.length} item(s) from Buffer` + - (size.backward ? `, +${size.backward} fwd px` : '') + - (size.forward ? `, +${size.forward} bwd px` : '') + - `, range: [${list[0]}..${list[list.length - 1]}]` - ] - : 'clipped 0 items from Buffer'; - }); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => { + const list = itemsToRemove.map(({ $index }) => $index); + return list.length + ? [ + `clipped ${list.length} item(s) from Buffer` + + (size.backward ? `, +${size.backward} fwd px` : '') + + (size.forward ? `, +${size.forward} bwd px` : '') + + `, range: [${list[0]}..${list[list.length - 1]}]` + ] + : 'clipped 0 items from Buffer'; + }); - logger.stat('after clip'); + logger.stat('after clip'); + } } } diff --git a/src/processes/fetch.ts b/src/processes/fetch.ts index 9f1b6cd7..a2f2a0de 100644 --- a/src/processes/fetch.ts +++ b/src/processes/fetch.ts @@ -22,10 +22,12 @@ export default class Fetch extends BaseProcessFactory(CommonProcess.fetch) { const box = { success: (data: unknown[]) => { - scroller.logger.log(() => - `resolved ${data.length} items ` + - `(index = ${scroller.state.fetch.index}, count = ${scroller.state.fetch.count})` - ); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => + `resolved ${data.length} items ` + + `(index = ${scroller.state.fetch.index}, count = ${scroller.state.fetch.count})` + ); + } scroller.state.fetch.newItemsData = data; workflow.call({ process: Fetch.process, diff --git a/src/processes/init.ts b/src/processes/init.ts index e93a6750..9dee56ef 100644 --- a/src/processes/init.ts +++ b/src/processes/init.ts @@ -9,7 +9,9 @@ export default class Init extends BaseProcessFactory(CommonProcess.init) { static run(scroller: Scroller, process: ProcessName): void { const { state, workflow } = scroller; const isInitial = initProcesses.includes(process); - scroller.logger.logCycle(true); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.logCycle(true); + } state.startWorkflowCycle(isInitial, process); workflow.call({ process: Init.process, diff --git a/src/processes/misc/base.ts b/src/processes/misc/base.ts index 3f96d679..c342f6e2 100644 --- a/src/processes/misc/base.ts +++ b/src/processes/misc/base.ts @@ -31,7 +31,9 @@ export const BaseAdapterProcessFactory = (process: AdapterProcess): IBaseAdapter [key]: value }), {} as T); } else { - scroller.logger.log(() => result.data.showErrors()); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => result.data.showErrors()); + } if (!ignoreErrors) { scroller.workflow.call({ process, diff --git a/src/processes/preClip.ts b/src/processes/preClip.ts index 57e68d8e..5a158271 100644 --- a/src/processes/preClip.ts +++ b/src/processes/preClip.ts @@ -23,17 +23,21 @@ export default class PreClip extends BaseProcessFactory(CommonProcess.preClip) { } const firstIndex = fetch.first.indexBuffer; const lastIndex = fetch.last.indexBuffer; - scroller.logger.log(() => - `looking for ${fetch.direction ? 'anti-' + fetch.direction + ' ' : ''}items ` + - `that are out of [${firstIndex}..${lastIndex}] range`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => + `looking for ${fetch.direction ? 'anti-' + fetch.direction + ' ' : ''}items ` + + `that are out of [${firstIndex}..${lastIndex}] range`); + } if (PreClip.isBackward(scroller, firstIndex)) { PreClip.prepareClipByDirection(scroller, Direction.backward, firstIndex); } if (PreClip.isForward(scroller, lastIndex)) { PreClip.prepareClipByDirection(scroller, Direction.forward, lastIndex); } - if (!clip.doClip) { - scroller.logger.log('skipping clip [no items to clip]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + if (!clip.doClip) { + scroller.logger.log('skipping clip [no items to clip]'); + } } return; } @@ -41,15 +45,21 @@ export default class PreClip extends BaseProcessFactory(CommonProcess.preClip) { static shouldNotClip(scroller: Scroller): boolean { const { settings, buffer, state } = scroller; if (settings.infinite && !state.clip.force) { - scroller.logger.log('skipping clip [infinite mode]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('skipping clip [infinite mode]'); + } return true; } if (!buffer.size) { - scroller.logger.log('skipping clip [empty buffer]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('skipping clip [empty buffer]'); + } return true; } if (state.cycle.isInitial) { - scroller.logger.log('skipping clip [initial cycle]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('skipping clip [initial cycle]'); + } return true; } return false; diff --git a/src/processes/preFetch.ts b/src/processes/preFetch.ts index d791b7b7..d637683e 100644 --- a/src/processes/preFetch.ts +++ b/src/processes/preFetch.ts @@ -36,7 +36,9 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) PreFetch.setPositions(scroller); PreFetch.setFirstIndex(scroller); PreFetch.setLastIndex(scroller); - scroller.logger.fetch(); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.fetch(); + } } static setPositions(scroller: Scroller): void { @@ -61,9 +63,11 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) for (let index = buffer.finiteAbsMinIndex; index < buffer.startIndex; index++) { startDelta += buffer.getSizeByIndex(index); } - scroller.logger.log(() => [ - `start delta is ${startDelta}`, ...(offset ? [` (+${offset} offset)`] : []) - ]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => [ + `start delta is ${startDelta}`, ...(offset ? [` (+${offset} offset)`] : []) + ]); + } return startDelta; } @@ -73,9 +77,13 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) let firstIndex = buffer.startIndex; let firstIndexPosition = 0; if (state.cycle.innerLoop.isInitial) { - scroller.logger.log('skipping fetch backward direction [initial loop]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('skipping fetch backward direction [initial loop]'); + } } else if (!buffer.defaultSize) { - scroller.logger.log('skipping fetch backward direction [no item size]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('skipping fetch backward direction [no item size]'); + } } else { let position = firstIndexPosition; let index = firstIndex; @@ -120,7 +128,9 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) if (!buffer.defaultSize) { // just to fetch forward bufferSize items if neither averageItemSize nor itemSize are present lastIndex = buffer.startIndex + settings.bufferSize - 1; - scroller.logger.log('forcing fetch forward direction [no item size]'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log('forcing fetch forward direction [no item size]'); + } } else { let index = first.indexBuffer; let position = first.position; @@ -174,8 +184,10 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) } fetch.first.index = Math.max(pack[0], buffer.absMinIndex); fetch.last.index = Math.min(pack[pack.length - 1], buffer.absMaxIndex); - if (fetch.first.index !== firstIndex || fetch.last.index !== lastIndex) { - scroller.logger.fetch('after Buffer flushing'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + if (fetch.first.index !== firstIndex || fetch.last.index !== lastIndex) { + scroller.logger.fetch('after Buffer flushing'); + } } } @@ -194,8 +206,10 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) if (fetchLast < bufferFirst) { fetch.last.index = fetch.last.indexBuffer = bufferFirst - 1; } - if (fetch.first.index !== fetchFirst || fetch.last.index !== fetchLast) { - scroller.logger.fetch('after Buffer filling (no clip case)'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + if (fetch.first.index !== fetchFirst || fetch.last.index !== fetchLast) { + scroller.logger.fetch('after Buffer filling (no clip case)'); + } } } @@ -222,7 +236,9 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) } } if (fetch.first.index !== firstIndex || fetch.last.index !== lastIndex) { - scroller.logger.fetch('after bufferSize adjustment'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.fetch('after bufferSize adjustment'); + } PreFetch.skipBufferedItems(scroller); } } @@ -235,18 +251,24 @@ export default class PreFetch extends BaseProcessFactory(CommonProcess.preFetch) direction = fetch.last.index < buffer.items[0].$index ? Direction.backward : Direction.forward; } fetch.direction = direction; - scroller.logger.log(() => `fetch direction is "${direction}"`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => `fetch direction is "${direction}"`); + } } } static getStatus(scroller: Scroller): ProcessStatus { const { cycle, fetch } = scroller.state; if (cycle.initiator === AdapterProcess.clip) { - scroller.logger.log(() => `going to skip fetch due to "${AdapterProcess.clip}" process`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => `going to skip fetch due to "${AdapterProcess.clip}" process`); + } return ProcessStatus.next; } if (fetch.shouldFetch) { - scroller.logger.log(() => `going to fetch ${fetch.count} items started from index ${fetch.index}`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => `going to fetch ${fetch.count} items started from index ${fetch.index}`); + } return ProcessStatus.next; } return ProcessStatus.done; diff --git a/src/processes/render.ts b/src/processes/render.ts index 1ffa1a11..b4b36aeb 100644 --- a/src/processes/render.ts +++ b/src/processes/render.ts @@ -6,7 +6,9 @@ export default class Render extends BaseProcessFactory(CommonProcess.render) { static run(scroller: Scroller): void { const { workflow, state: { cycle, render, scroll, fetch }, viewport, routines } = scroller; - scroller.logger.stat('before new items render'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.stat('before new items render'); + } if (scroll.positionBeforeAsync === null) { scroll.positionBeforeAsync = viewport.scrollPosition; } @@ -41,8 +43,10 @@ export default class Render extends BaseProcessFactory(CommonProcess.render) { } buffer.checkDefaultSize(); render.sizeAfter = viewport.getScrollableSize(); - logger.stat('after new items render'); - logger.log(() => render.noSize ? 'viewport size has not been changed' : void 0); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.stat('after new items render'); + logger.log(() => render.noSize ? 'viewport size has not been changed' : void 0); + } return true; } diff --git a/src/processes/scroll.ts b/src/processes/scroll.ts index f0a9ad74..2b7cf9ee 100644 --- a/src/processes/scroll.ts +++ b/src/processes/scroll.ts @@ -27,14 +27,18 @@ export default class Scroll extends BaseProcessFactory(CommonProcess.scroll) { scroll.syntheticPosition = null; } if (!scroll.syntheticFulfill || synthPos === position) { + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => [ + 'skipping scroll', position, `[${scroll.syntheticFulfill ? '' : 'pre-'}synthetic]` + ]); + } + return true; + } + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { scroller.logger.log(() => [ - 'skipping scroll', position, `[${scroll.syntheticFulfill ? '' : 'pre-'}synthetic]` + 'synthetic scroll has been fulfilled:', position, position < synthPos ? '<' : '>', synthPos ]); - return true; } - scroller.logger.log(() => [ - 'synthetic scroll has been fulfilled:', position, position < synthPos ? '<' : '>', synthPos - ]); } return false; } @@ -47,12 +51,14 @@ export default class Scroll extends BaseProcessFactory(CommonProcess.scroll) { const delta = throttle - timeDiff; const shouldDelay = isFinite(delta) && delta > 0; const alreadyDelayed = !!scroll.scrollTimer; - logger.log(() => [ - direction === Direction.backward ? '\u2934' : '\u2935', - position, - shouldDelay ? (timeDiff + 'ms') : '0ms', - shouldDelay ? (alreadyDelayed ? 'delayed' : `/ ${delta}ms delay`) : '' - ]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => [ + direction === Direction.backward ? '\u2934' : '\u2935', + position, + shouldDelay ? (timeDiff + 'ms') : '0ms', + shouldDelay ? (alreadyDelayed ? 'delayed' : `/ ${delta}ms delay`) : '' + ]); + } if (!shouldDelay) { if (scroll.scrollTimer) { clearTimeout(scroll.scrollTimer); @@ -63,16 +69,18 @@ export default class Scroll extends BaseProcessFactory(CommonProcess.scroll) { } if (!alreadyDelayed) { scroll.scrollTimer = setTimeout(() => { - logger.log(() => { - const curr = Scroll.getScrollEvent(scroller.viewport.scrollPosition, scroll.current); - return [ - curr.direction === Direction.backward ? '\u2934' : '\u2935', - curr.position, - (curr.time - time) + 'ms', - 'triggered by timer set on', - position - ]; - }); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => { + const curr = Scroll.getScrollEvent(scroller.viewport.scrollPosition, scroll.current); + return [ + curr.direction === Direction.backward ? '\u2934' : '\u2935', + curr.position, + (curr.time - time) + 'ms', + 'triggered by timer set on', + position + ]; + }); + } scroll.scrollTimer = null; done(); }, delta); @@ -98,7 +106,9 @@ export default class Scroll extends BaseProcessFactory(CommonProcess.scroll) { scroll.current = null; if (cycle.busy.get()) { - scroller.logger.log(() => ['skipping scroll', (scroll.previous as ScrollEventData).position, '[pending]']); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + scroller.logger.log(() => ['skipping scroll', (scroll.previous as ScrollEventData).position, '[pending]']); + } return; } diff --git a/src/scroller.ts b/src/scroller.ts index 40cb6f1b..c34fd123 100644 --- a/src/scroller.ts +++ b/src/scroller.ts @@ -55,12 +55,14 @@ export class Scroller { this.workflow = workflow; this.settings = new Settings(datasource.settings, datasource.devSettings, ++instanceCount); - this.logger = new Logger(this as Scroller, packageInfo, datasource.adapter); + this.logger = typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging ? new Logger(this as Scroller, packageInfo, datasource.adapter) : null!; this.routines = new (CustomRoutines || Routines)(element, this.settings); this.state = new State(packageInfo, this.settings, scroller ? scroller.state : void 0); this.buffer = new Buffer(this.settings, workflow.onDataChanged, this.logger); this.viewport = new Viewport(this.settings, this.routines, this.state, this.logger); - this.logger.object('vscroll settings object', this.settings, true); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.object('vscroll settings object', this.settings, true); + } this.initDatasource(datasource, scroller); } @@ -90,7 +92,9 @@ export class Scroller { init(adapterRun$?: Reactive): void { this.viewport.reset(this.buffer.startIndex); - this.logger.stat('initialization'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.stat('initialization'); + } this.adapter.initialize({ buffer: this.buffer, state: this.state, @@ -101,7 +105,9 @@ export class Scroller { } dispose(forever?: boolean): void { - this.logger.log(() => 'disposing scroller' + (forever ? ' (forever)' : '')); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.logger.log(() => 'disposing scroller' + (forever ? ' (forever)' : '')); + } if (forever) { // Adapter is not re-instantiated on reset this.adapter.dispose(); } diff --git a/src/workflow.ts b/src/workflow.ts index c3c05615..26846a0a 100644 --- a/src/workflow.ts +++ b/src/workflow.ts @@ -103,7 +103,9 @@ export class Workflow { // if the scroller is paused, any process other than "pause" and "reset" should be blocked if (this.scroller.state.paused.get()) { if (![AdapterProcess.pause, AdapterProcess.reset].includes(process as AdapterProcess)) { - this.scroller.logger.log('scroller is paused: ' + process + ' process is ignored'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.scroller.logger.log('scroller is paused: ' + process + ' process is ignored'); + } return; } } @@ -122,13 +124,15 @@ export class Workflow { process(data: ProcessSubject): void { const { status, process, payload } = data; - if (this.scroller.settings.logProcessRun) { - this.scroller.logger.log(() => [ - '%cfire%c', ...['color: #cc7777;', 'color: #000000;'], - process, `"${status}"`, ...(payload !== void 0 ? [payload] : []) - ]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + if (this.scroller.settings.logProcessRun) { + this.scroller.logger.log(() => [ + '%cfire%c', ...['color: #cc7777;', 'color: #000000;'], + process, `"${status}"`, ...(payload !== void 0 ? [payload] : []) + ]); + } + this.scroller.logger.logProcess(data); } - this.scroller.logger.logProcess(data); if (process === CommonProcess.end) { this.scroller.finalize(); @@ -142,11 +146,13 @@ export class Workflow { runProcess() { return ({ run, process, name }: ProcessClass) => (...args: unknown[]): void => { - if (this.scroller.settings.logProcessRun) { - this.scroller.logger.log(() => [ - '%crun%c', ...['color: #333399;', 'color: #000000;'], - process || name, ...args - ]); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + if (this.scroller.settings.logProcessRun) { + this.scroller.logger.log(() => [ + '%crun%c', ...['color: #333399;', 'color: #000000;'], + process || name, ...args + ]); + } } run(this.scroller as Scroller, ...args); }; @@ -161,7 +167,9 @@ export class Workflow { time, loop: cycle.loopIdNext }); - this.scroller.logger.logError(message); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.scroller.logger.logError(message); + } } interrupt({ process, finalize, datasource }: InterruptParams): void { @@ -174,11 +182,15 @@ export class Workflow { workflow.call.interrupted = true; this.scroller.workflow = this.getUpdater(); this.interruptionCount++; - logger.log(() => `workflow had been interrupted by the ${process} process (${this.interruptionCount})`); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + logger.log(() => `workflow had been interrupted by the ${process} process (${this.interruptionCount})`); + } } if (datasource) { // Scroller re-initialization case const reInit = () => { - this.scroller.logger.log('new Scroller instantiation'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.scroller.logger.log('new Scroller instantiation'); + } const scroller = new Scroller({ datasource, scroller: this.scroller }); this.scroller.dispose(); this.scroller = scroller; @@ -202,7 +214,9 @@ export class Workflow { } dispose(): void { - this.scroller.logger.log(() => 'disposing workflow'); + if (typeof vscroll_enableLogging === 'undefined' || vscroll_enableLogging) { + this.scroller.logger.log(() => 'disposing workflow'); + } if (this.initTimer) { clearTimeout(this.initTimer); }