mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-14 14:58:35 -04:00
Add API panel diagnostics
Former-commit-id: 6abf245be487184df940de711371b391d7188c22 [formerly bbe4eae66a2145cd2cfd24567cf5fcbb47dfc8a4] [formerly 30f3e73687d6aa1553f24e510a3dfb8fbf962eea] [formerly 4e6bf05eb8832d99b0a901afdf5f04da4a139cd5 [formerly c878386f65d7e8fb7bb6892819b6bdde2b88f026 [formerly 3cc8f4a84e2f47466f091deea978cbaf2dd81199]]] Former-commit-id: c47312aacc2a3a6bfd022f51b0d1425ae063b51c [formerly 86f190abe4a4089591109d52da05729b228def61 [formerly 988ab5fb5ee15886bb25080634e15850b9b89da9]] Former-commit-id: 193ab878120c550bf6f4b0021de0337cfd50fc29 [formerly 3cb45c31d996f76cb386dad153277dc8bf96067a] Former-commit-id: a7863e70a96ca7eb700248648e784ec02f002101
This commit is contained in:
parent
344d11bb3b
commit
abe5fe5ea6
@ -884,6 +884,8 @@
|
|||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div id="serviceWorkerStatus"></div>
|
<div id="serviceWorkerStatus"></div>
|
||||||
<div id="messageChannelStatus"></div>
|
<div id="messageChannelStatus"></div>
|
||||||
|
<div id="settingsStoreStatus"></div>
|
||||||
|
<div id="decompressorAPIStatus"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1626,7 +1626,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'sett
|
|||||||
*/
|
*/
|
||||||
function refreshAPIStatus() {
|
function refreshAPIStatus() {
|
||||||
var apiStatusPanel = document.getElementById('apiStatusDiv');
|
var apiStatusPanel = document.getElementById('apiStatusDiv');
|
||||||
apiStatusPanel.classList.remove('panel-success', 'panel-warning');
|
apiStatusPanel.classList.remove('panel-success', 'panel-warning', 'panel-danger');
|
||||||
var apiPanelClass = 'panel-success';
|
var apiPanelClass = 'panel-success';
|
||||||
if (isMessageChannelAvailable()) {
|
if (isMessageChannelAvailable()) {
|
||||||
$('#messageChannelStatus').html("MessageChannel API available");
|
$('#messageChannelStatus').html("MessageChannel API available");
|
||||||
@ -1655,7 +1655,28 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'sett
|
|||||||
$('#serviceWorkerStatus').removeClass("apiAvailable apiUnavailable")
|
$('#serviceWorkerStatus').removeClass("apiAvailable apiUnavailable")
|
||||||
.addClass("apiUnavailable");
|
.addClass("apiUnavailable");
|
||||||
}
|
}
|
||||||
apiStatusPanel.classList.add(apiPanelClass);
|
|
||||||
|
// Update Settings Store section of API panel with API name
|
||||||
|
var settingsStoreStatusDiv = document.getElementById('settingsStoreStatus');
|
||||||
|
var apiName = params.storeType === 'cookie' ? 'Cookie' : params.storeType === 'local_storage' ? 'Local Storage' : 'None';
|
||||||
|
settingsStoreStatusDiv.innerHTML = 'Settings Storage API in use: ' + apiName;
|
||||||
|
settingsStoreStatusDiv.classList.remove('apiAvailable', 'apiUnavailable');
|
||||||
|
settingsStoreStatusDiv.classList.add(params.storeType === 'none' ? 'apiUnavailable' : 'apiAvailable');
|
||||||
|
apiPanelClass = params.storeType === 'none' ? 'panel-warning' : apiPanelClass;
|
||||||
|
|
||||||
|
// Update Decompressor API section of panel
|
||||||
|
var decompAPIStatusDiv = document.getElementById('decompressorAPIStatus');
|
||||||
|
apiName = params.decompressorAPI.assemblerMachineType;
|
||||||
|
if (apiName && params.decompressorAPI.decompressorLastUsed) {
|
||||||
|
apiName += ' [ ' + params.decompressorAPI.decompressorLastUsed + ' ]';
|
||||||
|
}
|
||||||
|
apiPanelClass = params.decompressorAPI.errorStatus ? 'panel-danger' : apiName ? apiPanelClass : 'panel-warning';
|
||||||
|
decompAPIStatusDiv.className = apiName ? params.decompressorAPI.errorStatus ? 'apiBroken' : 'apiAvailable' : 'apiUnavailable';
|
||||||
|
apiName = params.decompressorAPI.errorStatus || apiName || 'Not initialized';
|
||||||
|
decompAPIStatusDiv.innerHTML = 'Decompressor API: ' + apiName;
|
||||||
|
|
||||||
|
// Add a warning colour to the API Status Panel if any of the above tests failed
|
||||||
|
apiStatusPanel.classList.add(apiPanelClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keepAliveServiceWorkerHandle;
|
var keepAliveServiceWorkerHandle;
|
||||||
@ -2230,6 +2251,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'sett
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileHandle) {
|
if (fileHandle) {
|
||||||
|
// Deal with split archives
|
||||||
if (/\.zim\w\w$/i.test(fileHandle.name)) {
|
if (/\.zim\w\w$/i.test(fileHandle.name)) {
|
||||||
var genericFileName = fileHandle.name.replace(/(\.zim)\w\w$/i, '$1');
|
var genericFileName = fileHandle.name.replace(/(\.zim)\w\w$/i, '$1');
|
||||||
var testFileName = new RegExp(genericFileName + '\\w\\w$');
|
var testFileName = new RegExp(genericFileName + '\\w\\w$');
|
||||||
@ -2242,11 +2264,13 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'sett
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Deal with single unslpit archive
|
||||||
fileset.push(fileHandle.getFile().then(function(file) {
|
fileset.push(fileHandle.getFile().then(function(file) {
|
||||||
return file;
|
return file;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (fileset.length) {
|
if (fileset.length) {
|
||||||
|
// Wait for all getFile Promises to resolve
|
||||||
Promise.all(fileset).then(function (resolvedFiles) {
|
Promise.all(fileset).then(function (resolvedFiles) {
|
||||||
setLocalArchiveFromFileList(resolvedFiles);
|
setLocalArchiveFromFileList(resolvedFiles);
|
||||||
});
|
});
|
||||||
|
@ -728,7 +728,20 @@ define(rqDef, function() {
|
|||||||
appstate.sessionScale = appstate.windowScale;
|
appstate.sessionScale = appstate.windowScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If global variable webpMachine was defined, then we need to initialize the WebP Polyfill
|
|
||||||
|
// Reports an error in loading one of the ASM or WASM machines to the UI API Status Panel
|
||||||
|
// This can't be done in aoo.js because the error occurs after the API panel is first displayed
|
||||||
|
function reportAssemblerErrorToAPIStatusPanel(decoderType, error) {
|
||||||
|
// Report error to API panel because error is produced asynchronously after panel is first displayed
|
||||||
|
console.error('Could not instantiate any ' + decoderType + ' decoder!', error);
|
||||||
|
params.decompressorAPI.errorStatus = 'Error loading ' + decoderType + ' decompressor!';
|
||||||
|
var decompAPI = document.getElementById('decompressorAPIStatus');
|
||||||
|
decompAPI.innerHTML = 'Decompressor API: ' + params.decompressorAPI.errorStatus;
|
||||||
|
decompAPI.className = 'apiBroken';
|
||||||
|
document.getElementById('apiStatusDiv').className = 'panel panel-danger';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If global variable webpMachine is true (set in init.js), then we need to initialize the WebP Polyfill
|
||||||
if (webpMachine) webpMachine = new webpHero.WebpMachine();
|
if (webpMachine) webpMachine = new webpHero.WebpMachine();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -754,6 +767,7 @@ define(rqDef, function() {
|
|||||||
systemAlert: systemAlert,
|
systemAlert: systemAlert,
|
||||||
checkServerIsAccessible: checkServerIsAccessible,
|
checkServerIsAccessible: checkServerIsAccessible,
|
||||||
htmlEscapeChars: htmlEscapeChars,
|
htmlEscapeChars: htmlEscapeChars,
|
||||||
initTouchZoom: initTouchZoom
|
initTouchZoom: initTouchZoom,
|
||||||
|
reportAssemblerErrorToAPIStatusPanel: reportAssemblerErrorToAPIStatusPanel
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -24,18 +24,20 @@
|
|||||||
// DEV: Put your RequireJS definition in the rqDefXZ array below, and any function exports in the function parenthesis of the define statement
|
// DEV: Put your RequireJS definition in the rqDefXZ array below, and any function exports in the function parenthesis of the define statement
|
||||||
// We need to do it this way in order to load the wasm or asm versions of xzdec conditionally. Older browsers can only use the asm version
|
// We need to do it this way in order to load the wasm or asm versions of xzdec conditionally. Older browsers can only use the asm version
|
||||||
// because they cannot interpret WebAssembly.
|
// because they cannot interpret WebAssembly.
|
||||||
var rqDefXZ = [];
|
var rqDefXZ = ['uiUtil'];
|
||||||
|
|
||||||
// Select asm or wasm conditionally
|
// Select asm or wasm conditionally
|
||||||
if ('WebAssembly' in self) {
|
if ('WebAssembly' in self) {
|
||||||
console.debug('Using WASM xz decoder');
|
console.debug('Instantiating WASM xz decoder');
|
||||||
|
params.decompressorAPI.assemblerMachineType = 'WASM';
|
||||||
rqDefXZ.push('xzdec-wasm');
|
rqDefXZ.push('xzdec-wasm');
|
||||||
} else {
|
} else {
|
||||||
console.debug('Using ASM xz decoder');
|
console.debug('Instantiating ASM xz decoder');
|
||||||
|
params.decompressorAPI.assemblerMachineType = 'ASM';
|
||||||
rqDefXZ.push('xzdec-asm');
|
rqDefXZ.push('xzdec-asm');
|
||||||
}
|
}
|
||||||
|
|
||||||
define(rqDefXZ, function() {
|
define(rqDefXZ, function(uiUtil) {
|
||||||
// DEV: xzdec.js has been compiled with `-s EXPORT_NAME="XZ" -s MODULARIZE=1` to avoid a clash with zstddec.js
|
// DEV: xzdec.js has been compiled with `-s EXPORT_NAME="XZ" -s MODULARIZE=1` to avoid a clash with zstddec.js
|
||||||
// Note that we include xzdec-asm or xzdec-wasm above in requireJS definition, but we cannot change the name in the function list
|
// Note that we include xzdec-asm or xzdec-wasm above in requireJS definition, but we cannot change the name in the function list
|
||||||
// There is no longer any need to load it in index.html
|
// There is no longer any need to load it in index.html
|
||||||
@ -49,27 +51,32 @@ define(rqDefXZ, function() {
|
|||||||
* The XZ Decoder instance
|
* The XZ Decoder instance
|
||||||
* @type EMSInstance
|
* @type EMSInstance
|
||||||
*/
|
*/
|
||||||
var xzdec;
|
var xzdec;
|
||||||
|
|
||||||
var instantiateDecoder = function (instance) {
|
XZ().then(function (instance) {
|
||||||
xzdec = instance;
|
// TEST ERROR CODE: UNCOMMENT TO TEST AND REMOVE BEFORE MERGE
|
||||||
};
|
// throw params.decompressorAPI.assemblerMachineType + ' broken!';
|
||||||
|
xzdec = instance;
|
||||||
XZ().then(instantiateDecoder)
|
}).catch(function (err) {
|
||||||
.catch(function (err) {
|
if (params.decompressorAPI.assemblerMachineType === 'ASM') {
|
||||||
console.debug(err);
|
// There is no fallback, because we were attempting to load the ASM machine, so report error immediately
|
||||||
if (/CompileError.+?WASM/i.test(err.message)) {
|
uiUtil.reportAssemblerErrorToAPIStatusPanel('XZ', err);
|
||||||
console.log("WASM failed to load, falling back to ASM...", err);
|
} else {
|
||||||
XZ = null;
|
console.warn('WASM failed to load, falling back to ASM...', err);
|
||||||
require(['xzdec-asm'], function() {
|
params.decompressorAPI.assemblerMachineType = 'ASM';
|
||||||
XZ().then(instantiateDecoder)
|
XZ = null;
|
||||||
.catch(function (err) {
|
require(['xzdec-asm'], function () {
|
||||||
console.error('Could not instantiate any decoder!', err);
|
XZ().then(function (instance) {
|
||||||
});
|
// TEST ERROR CODE: UNCOMMENT TO TEST AND REMOVE BEFORE MERGE
|
||||||
});
|
// throw params.decompressorAPI.assemblerMachineType + ' broken!';
|
||||||
}
|
xzdec = instance;
|
||||||
});
|
}).catch(function (err) {
|
||||||
|
uiUtil.reportAssemblerErrorToAPIStatusPanel('XZ', err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of milliseconds to wait for the decompressor to be available for another chunk
|
* Number of milliseconds to wait for the decompressor to be available for another chunk
|
||||||
* @type Integer
|
* @type Integer
|
||||||
@ -99,9 +106,11 @@ define(rqDefXZ, function() {
|
|||||||
* @returns {Decompressor}
|
* @returns {Decompressor}
|
||||||
*/
|
*/
|
||||||
function Decompressor(reader, chunkSize) {
|
function Decompressor(reader, chunkSize) {
|
||||||
|
params.decompressorAPI.decompressorLastUsed = 'XZ';
|
||||||
this._chunkSize = chunkSize || 1024 * 5;
|
this._chunkSize = chunkSize || 1024 * 5;
|
||||||
this._reader = reader;
|
this._reader = reader;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read length bytes, offset into the decompressed stream. Consecutive calls may only
|
* Read length bytes, offset into the decompressed stream. Consecutive calls may only
|
||||||
* advance in the stream and may not overlap.
|
* advance in the stream and may not overlap.
|
||||||
@ -122,7 +131,7 @@ define(rqDefXZ, function() {
|
|||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads stream of data from file offset for length of bytes to send to the decompresor
|
* Reads stream of data from file offset for length of bytes to send to the decompresor
|
||||||
* This function ensures that only one decompression runs at a time
|
* This function ensures that only one decompression runs at a time
|
||||||
@ -130,7 +139,7 @@ define(rqDefXZ, function() {
|
|||||||
* @param {Integer} length The amount of data to read
|
* @param {Integer} length The amount of data to read
|
||||||
* @returns {Promise} A Promise for the read data
|
* @returns {Promise} A Promise for the read data
|
||||||
*/
|
*/
|
||||||
Decompressor.prototype.readSliceSingleThread = function(offset, length) {
|
Decompressor.prototype.readSliceSingleThread = function (offset, length) {
|
||||||
// Tests whether the decompressor is ready (initiated) and not busy
|
// Tests whether the decompressor is ready (initiated) and not busy
|
||||||
if (xzdec && !busy) {
|
if (xzdec && !busy) {
|
||||||
return this.readSlice(offset, length);
|
return this.readSlice(offset, length);
|
||||||
@ -140,9 +149,9 @@ define(rqDefXZ, function() {
|
|||||||
// before using it for another decompression
|
// before using it for another decompression
|
||||||
var that = this;
|
var that = this;
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
setTimeout(function(){
|
setTimeout(function () {
|
||||||
that.readSliceSingleThread(offset, length).then(resolve, reject);
|
that.readSliceSingleThread(offset, length).then(resolve, reject);
|
||||||
}, DELAY_WAITING_IDLE_DECOMPRESSOR);
|
}, DELAY_WAITING_IDLE_DECOMPRESSOR);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
* Add Polyfill currently required by IE11 to run zstddec-asm and xzdec-asm
|
* Add Polyfill currently required by IE11 to run zstddec-asm and xzdec-asm
|
||||||
* See https://github.com/emscripten-core/emscripten/issues/14700
|
* See https://github.com/emscripten-core/emscripten/issues/14700
|
||||||
* If this is resolved upstream, remove this polyfill
|
* If this is resolved upstream, remove this polyfill
|
||||||
|
* Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
|
||||||
*/
|
*/
|
||||||
if (!String.prototype.startsWith) {
|
if (!String.prototype.startsWith) {
|
||||||
Object.defineProperty(String.prototype, 'startsWith', {
|
Object.defineProperty(String.prototype, 'startsWith', {
|
||||||
@ -35,6 +36,17 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A global variable to track the assembler machine type and the last used decompressor (for reporting to the API panel)
|
||||||
|
* This is populated in the Emscripten wrappers
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
params.decompressorAPI = {
|
||||||
|
assemblerMachineType: null,
|
||||||
|
decompressorLastUsed: null,
|
||||||
|
errorStatus: null
|
||||||
|
};
|
||||||
|
|
||||||
define(['xzdec_wrapper', 'zstddec_wrapper', 'util', 'utf8', 'zimDirEntry', 'filecache'], function(xz, zstd, util, utf8, zimDirEntry, FileCache) {
|
define(['xzdec_wrapper', 'zstddec_wrapper', 'util', 'utf8', 'zimDirEntry', 'filecache'], function(xz, zstd, util, utf8, zimDirEntry, FileCache) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,22 +24,24 @@
|
|||||||
// DEV: Put your RequireJS definition in the rqDefZD array below, and any function exports in the function parenthesis of the define statement
|
// DEV: Put your RequireJS definition in the rqDefZD array below, and any function exports in the function parenthesis of the define statement
|
||||||
// We need to do it this way in order to load the wasm or asm versions of zstddec conditionally. Older browsers can only use the asm version
|
// We need to do it this way in order to load the wasm or asm versions of zstddec conditionally. Older browsers can only use the asm version
|
||||||
// because they cannot interpret WebAssembly.
|
// because they cannot interpret WebAssembly.
|
||||||
var rqDefZD = [];
|
var rqDefZD = ['uiUtil'];
|
||||||
|
|
||||||
// Select asm or wasm conditionally
|
// Select asm or wasm conditionally
|
||||||
if ('WebAssembly' in self) {
|
if ('WebAssembly' in self) {
|
||||||
console.debug('Using WASM zstandard decoder');
|
console.debug('Instantiating WASM zstandard decoder');
|
||||||
|
params.decompressorAPI.assemblerMachineType = 'WASM';
|
||||||
rqDefZD.push('zstddec-wasm');
|
rqDefZD.push('zstddec-wasm');
|
||||||
} else {
|
} else {
|
||||||
console.debug('Using ASM zstandard decoder');
|
console.debug('Instantiating ASM zstandard decoder');
|
||||||
|
params.decompressorAPI.assemblerMachineType = 'ASM';
|
||||||
rqDefZD.push('zstddec-asm');
|
rqDefZD.push('zstddec-asm');
|
||||||
}
|
}
|
||||||
|
|
||||||
define(rqDefZD, function() {
|
define(rqDefZD, function(uiUtil) {
|
||||||
// DEV: zstddec.js has been compiled with `-s EXPORT_NAME="ZD" -s MODULARIZE=1` to avoid a clash with xzdec.js
|
// DEV: zstddec.js has been compiled with `-s EXPORT_NAME="ZD" -s MODULARIZE=1` to avoid a clash with xzdec.js
|
||||||
// Note that we include zstddec-wasm or zstddec-asm above in requireJS definition, but we cannot change the name in the function list
|
// Note that we include zstddec-wasm or zstddec-asm above in requireJS definition, but we cannot change the name in the function list
|
||||||
// For explanation of loading method below to avoid conflicts, see https://github.com/emscripten-core/emscripten/blob/master/src/settings.js
|
// For explanation of loading method below to avoid conflicts, see https://github.com/emscripten-core/emscripten/blob/master/src/settings.js
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef EMSInstanceExt An object type representing an Emscripten instance with extended properties
|
* @typedef EMSInstanceExt An object type representing an Emscripten instance with extended properties
|
||||||
* @property {Integer} _decHandle The decoder stream context object in asm memory (to be re-used for each decoder operation)
|
* @property {Integer} _decHandle The decoder stream context object in asm memory (to be re-used for each decoder operation)
|
||||||
@ -47,7 +49,7 @@ define(rqDefZD, function() {
|
|||||||
* @property {Object} _outBuffer A JS copy of the outBuffer structure to be set in asm memory (malloc)
|
* @property {Object} _outBuffer A JS copy of the outBuffer structure to be set in asm memory (malloc)
|
||||||
* @property {Integer} _chunkSize The number of compressed bytes to feed to the decompressor in any one read loop
|
* @property {Integer} _chunkSize The number of compressed bytes to feed to the decompressor in any one read loop
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ZSTD Decoder instance
|
* The ZSTD Decoder instance
|
||||||
* @type EMSInstanceExt
|
* @type EMSInstanceExt
|
||||||
@ -68,7 +70,7 @@ define(rqDefZD, function() {
|
|||||||
// Change _chunkSize if you need a more conservative memory environment, but you may need to experiment with INITIAL_MEMORY
|
// Change _chunkSize if you need a more conservative memory environment, but you may need to experiment with INITIAL_MEMORY
|
||||||
// in zstddec.js (see below) for this to make any difference
|
// in zstddec.js (see below) for this to make any difference
|
||||||
// zd._chunkSize = 5 * 1024;
|
// zd._chunkSize = 5 * 1024;
|
||||||
|
|
||||||
// Initialize inBuffer
|
// Initialize inBuffer
|
||||||
zd._inBuffer = {
|
zd._inBuffer = {
|
||||||
ptr: null, /* pointer to this inBuffer structure in w/asm memory */
|
ptr: null, /* pointer to this inBuffer structure in w/asm memory */
|
||||||
@ -80,7 +82,7 @@ define(rqDefZD, function() {
|
|||||||
zd._inBuffer.ptr = mallocOrDie(3 << 2); // 3 x 32bit bytes
|
zd._inBuffer.ptr = mallocOrDie(3 << 2); // 3 x 32bit bytes
|
||||||
// Reserve w/asm memory for the inBuffer data stream
|
// Reserve w/asm memory for the inBuffer data stream
|
||||||
zd._inBuffer.src = mallocOrDie(zd._inBuffer.size);
|
zd._inBuffer.src = mallocOrDie(zd._inBuffer.size);
|
||||||
|
|
||||||
// DEV: Size of outBuffer is currently set as recommended by zd._ZSTD_DStreamOutSize() below; if you are running into
|
// DEV: Size of outBuffer is currently set as recommended by zd._ZSTD_DStreamOutSize() below; if you are running into
|
||||||
// memory issues, it may be possible to reduce memory consumption by setting a smaller outBuffer size here and
|
// memory issues, it may be possible to reduce memory consumption by setting a smaller outBuffer size here and
|
||||||
// reompiling zstddec.js with lower TOTAL_MEMORY (or just search for INITIAL_MEMORY in zstddec.js and change it)
|
// reompiling zstddec.js with lower TOTAL_MEMORY (or just search for INITIAL_MEMORY in zstddec.js and change it)
|
||||||
@ -99,33 +101,42 @@ define(rqDefZD, function() {
|
|||||||
zd._outBuffer.dst = mallocOrDie(zd._outBuffer.size);
|
zd._outBuffer.dst = mallocOrDie(zd._outBuffer.size);
|
||||||
};
|
};
|
||||||
|
|
||||||
ZD().then(instantiateDecoder)
|
ZD().then(function (inst) {
|
||||||
.catch(function (err) {
|
// TEST ERROR CODE: UNCOMMENT TO TEST AND REMOVE BEFORE MERGE
|
||||||
console.debug(err);
|
// throw params.decompressorAPI.assemblerMachineType + ' broken!';
|
||||||
if (/CompileError.+?WASM/i.test(err.message)) {
|
instantiateDecoder(inst);
|
||||||
console.log("WASM failed to load, falling back to ASM...", err);
|
}).catch(function (err) {
|
||||||
|
if (params.decompressorAPI.assemblerMachineType === 'ASM') {
|
||||||
|
// There is no fallback, because we were attempting to load the ASM machine, so report error immediately
|
||||||
|
uiUtil.reportAssemblerErrorToAPIStatusPanel('ZSTD', err);
|
||||||
|
} else {
|
||||||
|
console.warn('WASM failed to load, falling back to ASM...', err);
|
||||||
|
params.decompressorAPI.assemblerMachineType = 'ASM';
|
||||||
ZD = null;
|
ZD = null;
|
||||||
require(['zstddec-asm'], function() {
|
require(['zstddec-asm'], function () {
|
||||||
ZD().then(instantiateDecoder)
|
ZD().then(function (inst) {
|
||||||
.catch(function (err) {
|
// TEST ERROR CODE: UNCOMMENT TO TEST AND REMOVE BEFORE MERGE
|
||||||
console.error('Could not instantiate any decoder!', err);
|
// throw params.decompressorAPI.assemblerMachineType + ' broken!';
|
||||||
|
instantiateDecoder(inst);
|
||||||
|
}).catch(function (err) {
|
||||||
|
uiUtil.reportAssemblerErrorToAPIStatusPanel('ZSTD', err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of milliseconds to wait for the decompressor to be available for another chunk
|
* Number of milliseconds to wait for the decompressor to be available for another chunk
|
||||||
* @type Integer
|
* @type Integer
|
||||||
*/
|
*/
|
||||||
var DELAY_WAITING_IDLE_DECOMPRESSOR = 50;
|
var DELAY_WAITING_IDLE_DECOMPRESSOR = 50;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the decompressor already working?
|
* Is the decompressor already working?
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
*/
|
*/
|
||||||
var busy = false;
|
var busy = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Decompressor
|
* @typedef Decompressor
|
||||||
* @property {FileReader} _reader The filereader to use (uses plain blob reader defined in zimfile.js)
|
* @property {FileReader} _reader The filereader to use (uses plain blob reader defined in zimfile.js)
|
||||||
@ -135,12 +146,13 @@ define(rqDefZD, function() {
|
|||||||
* @property {Array} _outDataBuf The buffer that stores decoded bytes (it is set to the requested blob's length, and when full, the data are returned)
|
* @property {Array} _outDataBuf The buffer that stores decoded bytes (it is set to the requested blob's length, and when full, the data are returned)
|
||||||
* @property {Integer} _outDataBufPos The number of bytes of the requested blob decoded so far
|
* @property {Integer} _outDataBufPos The number of bytes of the requested blob decoded so far
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {FileReader} reader The reader used to extract file slices (defined in zimfile.js)
|
* @param {FileReader} reader The reader used to extract file slices (defined in zimfile.js)
|
||||||
*/
|
*/
|
||||||
function Decompressor(reader) {
|
function Decompressor(reader) {
|
||||||
|
params.decompressorAPI.decompressorLastUsed = 'ZSTD';
|
||||||
this._reader = reader;
|
this._reader = reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +163,7 @@ define(rqDefZD, function() {
|
|||||||
* @param {Integer} length Number of decompressed bytes to read
|
* @param {Integer} length Number of decompressed bytes to read
|
||||||
* @returns {Promise<ArrayBuffer>} Promise for an ArrayBuffer with decoded data
|
* @returns {Promise<ArrayBuffer>} Promise for an ArrayBuffer with decoded data
|
||||||
*/
|
*/
|
||||||
Decompressor.prototype.readSlice = function(offset, length) {
|
Decompressor.prototype.readSlice = function (offset, length) {
|
||||||
busy = true;
|
busy = true;
|
||||||
this._inStreamPos = 0;
|
this._inStreamPos = 0;
|
||||||
this._inStreamChunkedPos = 0;
|
this._inStreamChunkedPos = 0;
|
||||||
@ -163,7 +175,7 @@ define(rqDefZD, function() {
|
|||||||
return Promise.reject('Failed to initialize ZSTD decompression');
|
return Promise.reject('Failed to initialize ZSTD decompression');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._readLoop(offset, length).then(function(data) {
|
return this._readLoop(offset, length).then(function (data) {
|
||||||
// DEV: We are re-using all the allocated w/asm memory, so we do not need to free any of structures assigned wiht _malloc
|
// DEV: We are re-using all the allocated w/asm memory, so we do not need to free any of structures assigned wiht _malloc
|
||||||
// However, should you need to free assigned structures use, e.g., zd._free(zd._inBuffer.src);
|
// However, should you need to free assigned structures use, e.g., zd._free(zd._inBuffer.src);
|
||||||
// Additionally, freeing zd._decHandle is not needed, and actually increases memory consumption (crashing zstddeclib)
|
// Additionally, freeing zd._decHandle is not needed, and actually increases memory consumption (crashing zstddeclib)
|
||||||
@ -217,7 +229,7 @@ define(rqDefZD, function() {
|
|||||||
// Get updated outbuffer values
|
// Get updated outbuffer values
|
||||||
var obxPtr32Bit = zd._outBuffer.ptr >> 2;
|
var obxPtr32Bit = zd._outBuffer.ptr >> 2;
|
||||||
var outPos = zd.HEAP32[obxPtr32Bit + 2];
|
var outPos = zd.HEAP32[obxPtr32Bit + 2];
|
||||||
|
|
||||||
// If data have been decompressed, check to see whether the data are in the offset range we need
|
// If data have been decompressed, check to see whether the data are in the offset range we need
|
||||||
if (outPos > 0 && that._outStreamPos + outPos >= offset) {
|
if (outPos > 0 && that._outStreamPos + outPos >= offset) {
|
||||||
var copyStart = offset - that._outStreamPos;
|
var copyStart = offset - that._outStreamPos;
|
||||||
@ -247,14 +259,14 @@ define(rqDefZD, function() {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills in the instream buffer
|
* Fills in the instream buffer
|
||||||
* @returns {Promise<0>} A Promise for 0 when all data have been added to the stream
|
* @returns {Promise<0>} A Promise for 0 when all data have been added to the stream
|
||||||
*/
|
*/
|
||||||
Decompressor.prototype._fillInBuffer = function() {
|
Decompressor.prototype._fillInBuffer = function () {
|
||||||
var that = this;
|
var that = this;
|
||||||
return this._reader(this._inStreamPos, zd._chunkSize).then(function(data) {
|
return this._reader(this._inStreamPos, zd._chunkSize).then(function (data) {
|
||||||
// Populate inBuffer and assign asm/wasm memory if not already assigned
|
// Populate inBuffer and assign asm/wasm memory if not already assigned
|
||||||
zd._inBuffer.size = data.length;
|
zd._inBuffer.size = data.length;
|
||||||
// Reset inBuffer
|
// Reset inBuffer
|
||||||
@ -265,7 +277,7 @@ define(rqDefZD, function() {
|
|||||||
var outBufferStruct = new Int32Array([zd._outBuffer.dst, zd._outBuffer.size, zd._outBuffer.pos]);
|
var outBufferStruct = new Int32Array([zd._outBuffer.dst, zd._outBuffer.size, zd._outBuffer.pos]);
|
||||||
// Write outBuffer structure to w/asm memory
|
// Write outBuffer structure to w/asm memory
|
||||||
zd.HEAP32.set(outBufferStruct, zd._outBuffer.ptr >> 2);
|
zd.HEAP32.set(outBufferStruct, zd._outBuffer.ptr >> 2);
|
||||||
|
|
||||||
// Transfer the (new) data to be read to the inBuffer
|
// Transfer the (new) data to be read to the inBuffer
|
||||||
zd.HEAPU8.set(data, zd._inBuffer.src);
|
zd.HEAPU8.set(data, zd._inBuffer.src);
|
||||||
that._inStreamChunkedPos += data.length;
|
that._inStreamChunkedPos += data.length;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user