Fix wrong test comparison. Add equality comparator to TileSource API. Return

deprecated support for getCompletionCallback. Turn on zombie cache if sources replaced & equal.
This commit is contained in:
Aiosa 2023-11-19 16:14:28 +01:00
parent 219049976c
commit 2a1090ffa8
11 changed files with 104 additions and 20 deletions

View File

@ -167,6 +167,14 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
}, },
/**
* Equality comparator
*/
equals: function(otherSource) {
return this.tilesUrl === otherSource.tilesUrl;
},
/** /**
* @function * @function
* @param {Number} level * @param {Number} level

View File

@ -503,6 +503,13 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
return uri; return uri;
}, },
/**
* Equality comparator
*/
equals: function(otherSource) {
return this._id === otherSource._id;
},
__testonly__: { __testonly__: {
canBeTiled: canBeTiled, canBeTiled: canBeTiled,
constructLevels: constructLevels constructLevels: constructLevels

View File

@ -180,6 +180,13 @@ $.ImageTileSource = class extends $.TileSource {
return `${this.url}?l=${level}&x=${x}&y=${y}`; return `${this.url}?l=${level}&x=${x}&y=${y}`;
} }
/**
* Equality comparator
*/
equals(otherSource) {
return this.url === otherSource.url;
}
getTilePostData(level, x, y) { getTilePostData(level, x, y) {
return {level: level, x: x, y: y}; return {level: level, x: x, y: y};
} }

View File

@ -187,6 +187,21 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, /** @lends OpenS
url = this.levels[ level ].url; url = this.levels[ level ].url;
} }
return url; return url;
},
/**
* Equality comparator
*/
equals: function (otherSource) {
if (!otherSource.levels || otherSource.levels.length !== this.levels.length) {
return false;
}
for (let i = this.minLevel; i <= this.maxLevel; i++) {
if (this.levels[i].url !== otherSource.levels[i].url) {
return false;
}
}
return true;
} }
} ); } );

View File

@ -139,6 +139,13 @@ $.extend( $.OsmTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
*/ */
getTileUrl: function( level, x, y ) { getTileUrl: function( level, x, y ) {
return this.tilesUrl + (level - 8) + "/" + x + "/" + y + ".png"; return this.tilesUrl + (level - 8) + "/" + x + "/" + y + ".png";
},
/**
* Equality comparator
*/
equals: function(otherSource) {
return this.tilesUrl === otherSource.tilesUrl;
} }
}); });

View File

@ -1785,13 +1785,19 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
// -> reason why it is not in the constructor // -> reason why it is not in the constructor
tile.setCache(tile.cacheKey, data, dataType, false, cutoff); tile.setCache(tile.cacheKey, data, dataType, false, cutoff);
let resolver = null; let resolver = null,
increment = 0,
eventFinished = false;
const _this = this, const _this = this,
finishPromise = new $.Promise(r => { finishPromise = new $.Promise(r => {
resolver = r; resolver = r;
}); });
function completionCallback() { function completionCallback() {
increment--;
if (increment > 0) {
return;
}
//do not override true if set (false is default) //do not override true if set (false is default)
tile.hasTransparency = tile.hasTransparency || _this.source.hasTransparency( tile.hasTransparency = tile.hasTransparency || _this.source.hasTransparency(
undefined, tile.getUrl(), tile.ajaxHeaders, tile.postData undefined, tile.getUrl(), tile.ajaxHeaders, tile.postData
@ -1823,6 +1829,17 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
tile.save(); tile.save();
} }
function getCompletionCallback() {
if (eventFinished) {
$.console.error("Event 'tile-loaded' argument getCompletionCallback must be called synchronously. " +
"Its return value should be called asynchronously.");
}
increment++;
return completionCallback;
}
const fallbackCompletion = getCompletionCallback();
/** /**
* Triggered when a tile has just been loaded in memory. That means that the * Triggered when a tile has just been loaded in memory. That means that the
* image has been downloaded and can be modified before being drawn to the canvas. * image has been downloaded and can be modified before being drawn to the canvas.
@ -1841,7 +1858,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @property {OpenSeadragon.Promise} - Promise resolved when the tile gets fully loaded. * @property {OpenSeadragon.Promise} - Promise resolved when the tile gets fully loaded.
* @property {function} getCompletionCallback - deprecated * @property {function} getCompletionCallback - deprecated
*/ */
const promise = this.viewer.raiseEventAwaiting("tile-loaded", { this.viewer.raiseEventAwaiting("tile-loaded", {
tile: tile, tile: tile,
tiledImage: this, tiledImage: this,
tileRequest: tileRequest, tileRequest: tileRequest,
@ -1855,13 +1872,15 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
return data; return data;
}, },
getCompletionCallback: function () { getCompletionCallback: function () {
$.console.error("[tile-loaded] getCompletionCallback is not supported: it is compulsory to handle the event with async functions if applicable."); $.console.error("[tile-loaded] getCompletionCallback is deprecated: it introduces race conditions: " +
"use async event handlers instead, execution order is deducted by addHandler(...) priority");
return getCompletionCallback();
}, },
}); }).catch(() => {
promise.then(completionCallback).catch(() => {
$.console.error("[tile-loaded] event finished with failure: there might be a problem with a plugin you are using."); $.console.error("[tile-loaded] event finished with failure: there might be a problem with a plugin you are using.");
completionCallback(); }).then(() => {
}); eventFinished = true;
}).then(fallbackCompletion);
}, },
/** /**

View File

@ -591,6 +591,17 @@ $.TileSource.prototype = {
return false; return false;
}, },
/**
* Check whether two tileSources are equal. This is used for example
* when replacing tile-sources, which turns on the zombie cache before
* old item removal.
* @param {OpenSeadragon.TileSource} otherSource
* @returns {Boolean}
*/
equals: function (otherSource) {
return false;
},
/** /**
* Responsible for parsing and configuring the * Responsible for parsing and configuring the
* image metadata pertinent to this TileSources implementation. * image metadata pertinent to this TileSources implementation.

View File

@ -131,6 +131,13 @@ $.extend( $.TmsTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
var yTiles = this.getNumTiles( level ).y - 1; var yTiles = this.getNumTiles( level ).y - 1;
return this.tilesUrl + level + "/" + x + "/" + (yTiles - y) + ".png"; return this.tilesUrl + level + "/" + x + "/" + (yTiles - y) + ".png";
},
/**
* Equality comparator
*/
equals: function (otherSource) {
return this.tilesUrl === otherSource.tilesUrl;
} }
}); });

View File

@ -1452,7 +1452,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* A set of headers to include when making tile AJAX requests. * A set of headers to include when making tile AJAX requests.
* Note that these headers will be merged over any headers specified in {@link OpenSeadragon.Options}. * Note that these headers will be merged over any headers specified in {@link OpenSeadragon.Options}.
* Specifying a falsy value for a header will clear its existing value set at the Viewer level (if any). * Specifying a falsy value for a header will clear its existing value set at the Viewer level (if any).
* @param {Function} [options.success] A function that gets called when the image is * @param {Function} [options.success] A function tadhat gets called when the image is
* successfully added. It's passed the event object which contains a single property: * successfully added. It's passed the event object which contains a single property:
* "item", which is the resulting instance of TiledImage. * "item", which is the resulting instance of TiledImage.
* @param {Function} [options.error] A function that gets called if the image is * @param {Function} [options.error] A function that gets called if the image is
@ -1575,11 +1575,15 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
_this._loadQueue.splice(0, 1); _this._loadQueue.splice(0, 1);
if (queueItem.options.replace) { if (queueItem.options.replace) {
var newIndex = _this.world.getIndexOfItem(queueItem.options.replaceItem); const replaced = queueItem.options.replaceItem;
const newIndex = _this.world.getIndexOfItem(replaced);
if (newIndex !== -1) { if (newIndex !== -1) {
queueItem.options.index = newIndex; queueItem.options.index = newIndex;
} }
_this.world.removeItem(queueItem.options.replaceItem); if (!replaced._zombieCache && replaced.source.equals(queueItem.tileSource)) {
replaced.allowZombieCache(true);
}
_this.world.removeItem(replaced);
} }
tiledImage = new $.TiledImage({ tiledImage = new $.TiledImage({

View File

@ -143,6 +143,13 @@
result = Math.floor(num / 256); result = Math.floor(num / 256);
return this.tilesUrl + 'TileGroup' + result + '/' + level + '-' + x + '-' + y + '.' + this.fileFormat; return this.tilesUrl + 'TileGroup' + result + '/' + level + '-' + x + '-' + y + '.' + this.fileFormat;
},
/**
* Equality comparator
*/
equals: function (otherSource) {
return this.tilesUrl === otherSource.tilesUrl;
} }
}); });

View File

@ -278,21 +278,13 @@
viewer.world.removeHandler('add-item', openHandler); viewer.world.removeHandler('add-item', openHandler);
viewer.world.addHandler('add-item', reopenHandler); viewer.world.addHandler('add-item', reopenHandler);
const oldCacheSize = event.item._tileCache._cachesLoadedCount + waitFor(() => {
event.item._tileCache._zombiesLoadedCount;
waitFor(() => {
if (tilesFinished === jobCounter && event.item._fullyLoaded) { if (tilesFinished === jobCounter && event.item._fullyLoaded) {
coverage = $.extend(true, {}, event.item.coverage); coverage = $.extend(true, {}, event.item.coverage);
viewer.addTiledImage({ viewer.addTiledImage({
tileSource: '/test/data/testpattern.dzi', tileSource: '/test/data/testpattern.dzi',
index: 0, index: 0,
replace: true, replace: true
success: e => {
test.equal(oldCacheSize, e.item._tileCache._cachesLoadedCount +
e.item._tileCache._zombiesLoadedCount,
"Image replace should erase no cache with zombies.");
}
}); });
return true; return true;
} }