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
* @param {Number} level

View File

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

View File

@ -180,6 +180,13 @@ $.ImageTileSource = class extends $.TileSource {
return `${this.url}?l=${level}&x=${x}&y=${y}`;
}
/**
* Equality comparator
*/
equals(otherSource) {
return this.url === otherSource.url;
}
getTilePostData(level, x, 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;
}
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 ) {
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
tile.setCache(tile.cacheKey, data, dataType, false, cutoff);
let resolver = null;
let resolver = null,
increment = 0,
eventFinished = false;
const _this = this,
finishPromise = new $.Promise(r => {
resolver = r;
});
function completionCallback() {
increment--;
if (increment > 0) {
return;
}
//do not override true if set (false is default)
tile.hasTransparency = tile.hasTransparency || _this.source.hasTransparency(
undefined, tile.getUrl(), tile.ajaxHeaders, tile.postData
@ -1823,6 +1829,17 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
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
* 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 {function} getCompletionCallback - deprecated
*/
const promise = this.viewer.raiseEventAwaiting("tile-loaded", {
this.viewer.raiseEventAwaiting("tile-loaded", {
tile: tile,
tiledImage: this,
tileRequest: tileRequest,
@ -1855,13 +1872,15 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
return data;
},
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();
},
});
promise.then(completionCallback).catch(() => {
}).catch(() => {
$.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;
},
/**
* 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
* 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;
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.
* 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).
* @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:
* "item", which is the resulting instance of TiledImage.
* @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);
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) {
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({

View File

@ -143,6 +143,13 @@
result = Math.floor(num / 256);
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.addHandler('add-item', reopenHandler);
const oldCacheSize = event.item._tileCache._cachesLoadedCount +
event.item._tileCache._zombiesLoadedCount;
waitFor(() => {
waitFor(() => {
if (tilesFinished === jobCounter && event.item._fullyLoaded) {
coverage = $.extend(true, {}, event.item.coverage);
viewer.addTiledImage({
tileSource: '/test/data/testpattern.dzi',
index: 0,
replace: true,
success: e => {
test.equal(oldCacheSize, e.item._tileCache._cachesLoadedCount +
e.item._tileCache._zombiesLoadedCount,
"Image replace should erase no cache with zombies.");
}
replace: true
});
return true;
}