From 47419a090acb657a0c9bb9047a2b5493c5a309e7 Mon Sep 17 00:00:00 2001 From: Aiosa <469130@mail.muni.cz> Date: Mon, 4 Mar 2024 10:49:05 +0100 Subject: [PATCH] Fix circular references in JSON test log serialization. --- src/tiledimage.js | 2 -- test/helpers/test.js | 36 +++++++++++++++++++++----- test/modules/tilesource-dynamic-url.js | 27 +++++++------------ 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/tiledimage.js b/src/tiledimage.js index 5efcc3b1..ff1af4b1 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -2107,8 +2107,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag } this._setTileLoaded(tile, data, null, tileRequest, dataType); - - //TODO aiosa missing timeout might damage the cache system }, /** diff --git a/test/helpers/test.js b/test/helpers/test.js index c8231686..cb9fe35c 100644 --- a/test/helpers/test.js +++ b/test/helpers/test.js @@ -180,14 +180,36 @@ } }; + // OSD has circular references, if a console log tries to serialize + // certain object, remove these references from a clone (do not delete prop + // on the original object). + // NOTE: this does not work if someone replaces the original class with + // a mock object! Try to mock functions only, or ensure mock objects + // do not hold circular references. + const circularOSDReferences = { + 'Tile': 'tiledImage', + 'World': 'viewer', + 'DrawerBase': ['viewer', 'viewport'], + 'CanvasDrawer': ['viewer', 'viewport'], + 'WebGLDrawer': ['viewer', 'viewport'], + 'TiledImage': ['viewer', '_drawer'], + }; for ( var i in testLog ) { if ( testLog.hasOwnProperty( i ) && testLog[i].push ) { - //Tile.tiledImage creates circular reference, copy object to avoid and allow JSON serialization - const tileCircularStructureReplacer = function (key, value) { - if (value instanceof OpenSeadragon.Tile) { - var instance = {}; - Object.assign(instance, value); - delete value.tiledImage; + // Circular reference removal + const osdCircularStructureReplacer = function (key, value) { + for (let ClassType in circularOSDReferences) { + if (value instanceof OpenSeadragon[ClassType]) { + const instance = {}; + Object.assign(instance, value); + + let circProps = circularOSDReferences[ClassType]; + if (!Array.isArray(circProps)) circProps = [circProps]; + for (let prop of circProps) { + instance[prop] = '__circular_reference__'; + } + return instance; + } } return value; }; @@ -195,7 +217,7 @@ testConsole[i] = ( function ( arr ) { return function () { var args = Array.prototype.slice.call( arguments, 0 ); // Coerce to true Array - arr.push( JSON.stringify( args, tileCircularStructureReplacer ) ); // Store as JSON to avoid tedious array-equality tests + arr.push( JSON.stringify( args, osdCircularStructureReplacer ) ); // Store as JSON to avoid tedious array-equality tests }; } )( testLog[i] ); diff --git a/test/modules/tilesource-dynamic-url.js b/test/modules/tilesource-dynamic-url.js index 099530af..59e33c1f 100644 --- a/test/modules/tilesource-dynamic-url.js +++ b/test/modules/tilesource-dynamic-url.js @@ -8,7 +8,7 @@ var DYNAMIC_URL = ""; var viewer = null; var OriginalAjax = OpenSeadragon.makeAjaxRequest; - var OriginalTile = OpenSeadragon.Tile; + var OriginalTileGetUrl = OpenSeadragon.Tile.prototype.getUrl; // These variables allow tracking when the first request for data has finished var firstUrlPromise = null; var isFirstUrlPromiseResolved = false; @@ -115,22 +115,15 @@ return request; }; - // Override Tile to ensure getUrl is called successfully. - var Tile = function(...params) { - OriginalTile.apply(this, params); - }; - - OpenSeadragon.extend( Tile.prototype, OpenSeadragon.Tile.prototype, { - getUrl: function() { - // if ASSERT is still truthy, call ASSERT.ok. If the viewer - // has already been destroyed and ASSERT has set to null, ignore this - if(ASSERT){ - ASSERT.ok(true, 'Tile.getUrl called'); - } - return OriginalTile.prototype.getUrl.apply(this); + // Override Tile::getUrl to ensure getUrl is called successfully. + OpenSeadragon.Tile.prototype.getUrl = function () { + // if ASSERT is still truthy, call ASSERT.ok. If the viewer + // has already been destroyed and ASSERT has set to null, ignore this + if (ASSERT) { + ASSERT.ok(true, 'Tile.getUrl called'); } - }); - OpenSeadragon.Tile = Tile; + return OriginalTileGetUrl.apply(this, arguments); + }; }, afterEach: function () { @@ -143,7 +136,7 @@ viewer = null; OpenSeadragon.makeAjaxRequest = OriginalAjax; - OpenSeadragon.Tile = OriginalTile; + OpenSeadragon.Tile.prototype.getUrl = OriginalTileGetUrl; } });