Fix memory issues

Former-commit-id: 3523937e13175610cd516968174f1403675500b5 [formerly eb79c290efd7ff9d0710d0f8ac8d72e7fcb5a30b] [formerly cd8660f1cdfd2c69728aa8a3bf93b50255902b82] [formerly 513913cb38d94c86b0e1b62657d9682420360120 [formerly 17d84e571a88071850bdd462395ad3dd540006b8 [formerly 6ea3f6a62e410dd6c9f8313fb1498d8a8a3f6388]]]
Former-commit-id: 68398e55efae1db32da3142118acaada5f821b32 [formerly 78891836e99634606af52ba4beddb36aab969071 [formerly 96eeafc04911f4a36a86e96e69870c2708fc0290]]
Former-commit-id: f57e0da2589c945c52ee8b58f92e6b47c00ab584 [formerly c71c78a09ecbc86cbface5bb1510f4cf327106af]
Former-commit-id: bcb00d466675411c7533f1d45f223c92eb8f7534
This commit is contained in:
Jaifroid 2021-07-17 12:42:57 +01:00
parent 5c27860a3a
commit 40ef8ede77
6 changed files with 1058 additions and 1352 deletions

View File

@ -248,7 +248,7 @@
<a class="btn btn-primary" style="display:none;" title="Back" id="btnBackAlt"><span class="glyphicon glyphicon-circle-arrow-left"></span></a>
<a class="btn btn-primary" style="display:none;" title="Forward" id="btnForwardAlt"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
</span>
<input type="search" id="prefix" placeholder="Search [with .*] or type a space..."
<input type="search" id="prefix" placeholder="Search [.*] or type a space..."
class="form-control" style="z-index: 0; width: 99.5%" />
<span class="input-group-btn">
<a class="btn btn-primary" title="Article Search" id="searchArticles" style="display:none;"><span class="glyphicon glyphicon-book"></span></a>

View File

@ -429,8 +429,7 @@ require.config({
},
'bootstrap': {
deps: ['jquery']
},
'webpHeroBundle': ''
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -1,170 +1,170 @@
/**
* xzdec_wrapper.js: Javascript wrapper around compiled xz decompressor.
*
* Copyright 2015 Mossroy and contributors
* License GPL v3:
*
* This file is part of Kiwix.
*
* Kiwix is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiwix is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
*/
'use strict';
define(['xzdec'], function() {
// DEV: xzdec.js emits a global Module variable, which cannot be set in requireJS function line above, though it can be loaded in definition
var xzdec = Module;
xzdec._init();
/**
* Number of milliseconds to wait for the decompressor to be available for another chunk
* @type Integer
*/
var DELAY_WAITING_IDLE_DECOMPRESSOR = 50;
/**
* Is the decompressor already working?
* @type Boolean
*/
var busy = false;
/**
* @typedef Decompressor
* @property {Integer} _chunkSize
* @property {FileReader} _reader
* @property {unresolved} _decHandle
* @property {Integer} _inStreamPos
* @property {Integer} _outStreamPos
* @property {Array} _outBuffer
*/
/**
* @constructor
* @param {FileReader} reader
* @param {Integer} chunkSize
* @returns {Decompressor}
*/
function Decompressor(reader, chunkSize) {
this._chunkSize = chunkSize || 1024 * 5;
this._reader = reader;
};
/**
* Read length bytes, offset into the decompressed stream. Consecutive calls may only
* advance in the stream and may not overlap.
* @param {Integer} offset
* @param {Integer} length
*/
Decompressor.prototype.readSlice = function(offset, length) {
busy = true;
var that = this;
this._inStreamPos = 0;
this._outStreamPos = 0;
this._decHandle = xzdec._init_decompression(this._chunkSize);
this._outBuffer = new Int8Array(new ArrayBuffer(length));
this._outBufferPos = 0;
return this._readLoop(offset, length).then(function(data) {
xzdec._release(that._decHandle);
busy = false;
return data;
});
};
/**
* 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
* @param {Integer} offset The file offset at which to begin reading compressed data
* @param {Integer} length The amount of data to read
* @returns {Promise} A Promise for the read data
*/
Decompressor.prototype.readSliceSingleThread = function(offset, length) {
if (!busy) {
return this.readSlice(offset, length);
} else {
// The decompressor is already in progress.
// To avoid using too much memory, we wait until it has finished
// before using it for another decompression
var that = this;
return new Promise(function (resolve, reject) {
setTimeout(function(){
that.readSliceSingleThread(offset, length).then(resolve, reject);
}, DELAY_WAITING_IDLE_DECOMPRESSOR);
});
}
};
/**
*
* @param {Integer} offset
* @param {Integer} length
* @returns {Array}
*/
Decompressor.prototype._readLoop = function(offset, length) {
var that = this;
return this._fillInBufferIfNeeded().then(function() {
var ret = xzdec._decompress(that._decHandle);
var finished = false;
if (ret === 0) {
// supply more data or free output buffer
} else if (ret === 1) {
// stream ended
finished = true;
} else {
// error @todo handle
finished = true;
}
var outPos = xzdec._get_out_pos(that._decHandle);
if (outPos > 0 && that._outStreamPos + outPos >= offset)
{
var outBuffer = xzdec._get_out_buffer(that._decHandle);
var copyStart = offset - that._outStreamPos;
if (copyStart < 0)
copyStart = 0;
for (var i = copyStart; i < outPos && that._outBufferPos < that._outBuffer.length; i++)
that._outBuffer[that._outBufferPos++] = xzdec.HEAP8[outBuffer + i];
}
that._outStreamPos += outPos;
if (outPos > 0)
xzdec._out_buffer_cleared(that._decHandle);
if (finished || that._outStreamPos >= offset + length)
return that._outBuffer;
else
return that._readLoop(offset, length);
});
};
/**
*
* @returns {Promise}
*/
Decompressor.prototype._fillInBufferIfNeeded = function() {
if (!xzdec._input_empty(this._decHandle)) {
// DEV: When converting to Promise/A+, use Promise.resolve(0) here
return Promise.resolve(0);
}
var that = this;
return this._reader(this._inStreamPos, this._chunkSize).then(function(data) {
if (data.length > that._chunkSize)
data = data.slice(0, that._chunkSize);
// For some reason, xzdec.writeArrayToMemory does not seem to be available, and is equivalent to xzdec.HEAP8.set
xzdec.HEAP8.set(data, xzdec._get_in_buffer(that._decHandle));
that._inStreamPos += data.length;
xzdec._set_new_input(that._decHandle, data.length);
return 0;
});
};
return {
Decompressor: Decompressor
};
});
/**
* xzdec_wrapper.js: Javascript wrapper around compiled xz decompressor.
*
* Copyright 2015 Mossroy and contributors
* License GPL v3:
*
* This file is part of Kiwix.
*
* Kiwix is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiwix is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
*/
'use strict';
define(['xzdec'], function() {
// DEV: xzdec.js emits a global Module variable, which cannot be set in requireJS function line above, though it can be loaded in definition
var xzdec = Module;
xzdec._init();
/**
* Number of milliseconds to wait for the decompressor to be available for another chunk
* @type Integer
*/
var DELAY_WAITING_IDLE_DECOMPRESSOR = 50;
/**
* Is the decompressor already working?
* @type Boolean
*/
var busy = false;
/**
* @typedef Decompressor
* @property {Integer} _chunkSize
* @property {FileReader} _reader
* @property {unresolved} _decHandle
* @property {Integer} _inStreamPos
* @property {Integer} _outStreamPos
* @property {Array} _outBuffer
*/
/**
* @constructor
* @param {FileReader} reader
* @param {Integer} chunkSize
* @returns {Decompressor}
*/
function Decompressor(reader, chunkSize) {
this._chunkSize = chunkSize || 1024 * 5;
this._reader = reader;
};
/**
* Read length bytes, offset into the decompressed stream. Consecutive calls may only
* advance in the stream and may not overlap.
* @param {Integer} offset
* @param {Integer} length
*/
Decompressor.prototype.readSlice = function(offset, length) {
busy = true;
var that = this;
this._inStreamPos = 0;
this._outStreamPos = 0;
this._decHandle = xzdec._init_decompression(this._chunkSize);
this._outBuffer = new Int8Array(new ArrayBuffer(length));
this._outBufferPos = 0;
return this._readLoop(offset, length).then(function(data) {
xzdec._release(that._decHandle);
busy = false;
return data;
});
};
/**
* 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
* @param {Integer} offset The file offset at which to begin reading compressed data
* @param {Integer} length The amount of data to read
* @returns {Promise} A Promise for the read data
*/
Decompressor.prototype.readSliceSingleThread = function(offset, length) {
if (xzdec && !busy) {
return this.readSlice(offset, length);
} else {
// The decompressor is already in progress.
// To avoid using too much memory, we wait until it has finished
// before using it for another decompression
var that = this;
return new Promise(function (resolve, reject) {
setTimeout(function(){
that.readSliceSingleThread(offset, length).then(resolve, reject);
}, DELAY_WAITING_IDLE_DECOMPRESSOR);
});
}
};
/**
*
* @param {Integer} offset
* @param {Integer} length
* @returns {Array}
*/
Decompressor.prototype._readLoop = function(offset, length) {
var that = this;
return this._fillInBufferIfNeeded().then(function() {
var ret = xzdec._decompress(that._decHandle);
var finished = false;
if (ret === 0) {
// supply more data or free output buffer
} else if (ret === 1) {
// stream ended
finished = true;
} else {
// error @todo handle
finished = true;
}
var outPos = xzdec._get_out_pos(that._decHandle);
if (outPos > 0 && that._outStreamPos + outPos >= offset)
{
var outBuffer = xzdec._get_out_buffer(that._decHandle);
var copyStart = offset - that._outStreamPos;
if (copyStart < 0)
copyStart = 0;
for (var i = copyStart; i < outPos && that._outBufferPos < that._outBuffer.length; i++)
that._outBuffer[that._outBufferPos++] = xzdec.HEAP8[outBuffer + i];
}
that._outStreamPos += outPos;
if (outPos > 0)
xzdec._out_buffer_cleared(that._decHandle);
if (finished || that._outStreamPos >= offset + length)
return that._outBuffer;
else
return that._readLoop(offset, length);
});
};
/**
*
* @returns {Promise}
*/
Decompressor.prototype._fillInBufferIfNeeded = function() {
if (!xzdec._input_empty(this._decHandle)) {
// DEV: When converting to Promise/A+, use Promise.resolve(0) here
return Promise.resolve(0);
}
var that = this;
return this._reader(this._inStreamPos, this._chunkSize).then(function(data) {
if (data.length > that._chunkSize)
data = data.slice(0, that._chunkSize);
// For some reason, xzdec.writeArrayToMemory does not seem to be available, and is equivalent to xzdec.HEAP8.set
xzdec.HEAP8.set(data, xzdec._get_in_buffer(that._decHandle));
that._inStreamPos += data.length;
xzdec._set_new_input(that._decHandle, data.length);
return 0;
});
};
return {
Decompressor: Decompressor
};
});

View File

@ -8,7 +8,11 @@ function(ZD) {
var a;a||(a=typeof ZD !== 'undefined' ? ZD : {});
var u,v;a.ready=new Promise(function(c,e){u=c;v=e});var w={},x;for(x in a)a.hasOwnProperty(x)&&(w[x]=a[x]);var y="";document.currentScript&&(y=document.currentScript.src);_scriptDir&&(y=_scriptDir);
var Promise=function(){function c(){}function e(b,f){return function(){b.apply(f,arguments)}}function d(b){if(!(this instanceof d))throw new TypeError("Promises must be constructed via new");if("function"!==typeof b)throw new TypeError("not a function");this.u=0;this.C=!1;this.v=void 0;this.w=[];D(b,this)}function m(b,f){for(;3===b.u;)b=b.v;0===b.u?b.w.push(f):(b.C=!0,d.D(function(){var g=1===b.u?f.G:f.H;if(null===g)(1===b.u?l:p)(f.B,b.v);else{try{var h=g(b.v)}catch(k){p(f.B,k);return}l(f.B,h)}}))}
function l(b,f){try{if(f===b)throw new TypeError("A promise cannot be resolved with itself.");if(f&&("object"===typeof f||"function"===typeof f)){var g=f.then;if(f instanceof d){b.u=3;b.v=f;r(b);return}if("function"===typeof g){D(e(g,f),b);return}}b.u=1;b.v=f;r(b)}catch(h){p(b,h)}}function p(b,f){b.u=2;b.v=f;r(b)}function r(b){2===b.u&&0===b.w.length&&d.D(function(){b.C||d.I(b.v)});for(var f=0,g=b.w.length;f<g;f++)m(b,b.w[f]);b.w=null}function q(b,f,g){this.G="function"===typeof b?b:null;this.H="function"===
typeof f?f:null;this.B=g}function D(b,f){var g=!1;try{b(function(h){g||(g=!0,l(f,h))},function(h){g||(g=!0,p(f,h))})}catch(h){g||(g=!0,p(f,h))}}d.prototype["catch"]=function(b){return this.then(null,b)};d.prototype.then=function(b,f){var g=new this.constructor(c);m(this,new q(b,f,g));return g};d.all=function(b){return new d(function(f,g){function h(I,z){try{if(z&&("object"===typeof z||"function"===typeof z)){var S=z.then;if("function"===typeof S){S.call(z,function(N){h(I,N)},g);return}}k[I]=z;0===
--t&&f(k)}catch(N){g(N)}}if(!Array.isArray(b))return g(new TypeError("Promise.all accepts an array"));var k=Array.prototype.slice.call(b);if(0===k.length)return f([]);for(var t=k.length,n=0;n<k.length;n++)h(n,k[n])})};d.resolve=function(b){return b&&"object"===typeof b&&b.constructor===d?b:new d(function(f){f(b)})};d.reject=function(b){return new d(function(f,g){g(b)})};d.race=function(b){return new d(function(f,g){if(!Array.isArray(b))return g(new TypeError("Promise.race accepts an array"));for(var h=
0,k=b.length;h<k;h++)d.resolve(b[h]).then(f,g)})};d.D="function"===typeof setImmediate&&function(b){setImmediate(b)}||function(b){setTimeout(b,0)};d.I=function(b){"undefined"!==typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",b)};return d}(),u,v;a.ready=new Promise(function(c,e){u=c;v=e});var w={},x;for(x in a)a.hasOwnProperty(x)&&(w[x]=a[x]);var y="";document.currentScript&&(y=document.currentScript.src);_scriptDir&&(y=_scriptDir);
0!==y.indexOf("blob:")?y=y.substr(0,y.lastIndexOf("/")+1):y="";var A=a.printErr||console.warn.bind(console);for(x in w)w.hasOwnProperty(x)&&(a[x]=w[x]);w=null;var B;a.wasmBinary&&(B=a.wasmBinary);var noExitRuntime;a.noExitRuntime&&(noExitRuntime=a.noExitRuntime);function aa(){this.buffer=new ArrayBuffer(C/65536*65536);this.grow=function(c){return E(c)}}function ba(){this.exports=(
// EMSCRIPTEN_START_ASM
function a(asmLibraryArg,wasmMemory,wasmTable){function b(global,env,buffer){var memory=env.a;var c=wasmTable;var d=new global.Int8Array(buffer);var e=new global.Int16Array(buffer);var f=new global.Int32Array(buffer);var g=new global.Uint8Array(buffer);var h=new global.Uint16Array(buffer);var i=new global.Uint32Array(buffer);var j=new global.Float32Array(buffer);var k=new global.Float64Array(buffer);var l=global.Math.imul;var m=global.Math.fround;var n=global.Math.abs;var o=global.Math.clz32;var p=global.Math.min;var q=global.Math.max;var r=global.Math.floor;var s=global.Math.ceil;var t=global.Math.sqrt;var u=env.abort;var v=global.NaN;var w=global.Infinity;var x=env.c;var y=env.d;var z=5248768;var A=0;

View File

@ -152,7 +152,7 @@ define(['zstddec'], function() {
* @returns {Promise} A Promise for the readSlice() function
*/
Decompressor.prototype.readSliceSingleThread = function (offset, length) {
if (!appstate.zdBusy) {
if (zd && !appstate.zdBusy) {
return this.readSlice(offset, length);
} else {
// The decompressor is already in progress.