mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-09 04:06:27 -04:00
Implement WASM with fallback (#174)
Former-commit-id: c68596bc74e187de64dc2e39e43eadcf1f9ea32f [formerly fa761722a44f952ce2dd17b8c9944b2b4f83adbf] [formerly f3cc4ecfb825af85e764ab89d1b350cdaca4b5e2] [formerly 2ce10066e6d7b53aa1390d7e75189f18c7b59b8a [formerly e7fe66c76d904f511bfa246c059dade2d12911b6 [formerly 40d3b58c2cf6821c94cb138f86d45c498698beed]]] Former-commit-id: 375cfb19d2c3ca7fcda82adff21837dcaecc2e82 [formerly a9650d1a4d00e1bc0ad8c82cb360c7c79cae2173 [formerly 7d6ea7d5e4332e09c8aa04e00d50c402a6ae0d16]] Former-commit-id: cba19c61686b992d81f8736997ed56ad669ea3cd [formerly 34f89f43b796b52dc5ff580d4f481a7d1b5ef7fc] Former-commit-id: a769646441e4eb51a6ee4485f594d46a98d1ce93
This commit is contained in:
parent
3bee578801
commit
9728d41fc9
43
.gitattributes
vendored
Normal file
43
.gitattributes
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text eol=lf
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
|
||||
*.png binary
|
||||
*.jpeg binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
*.dat binary
|
||||
*.idx binary
|
||||
*.zip binary
|
||||
*.gz binary
|
||||
*.odt binary
|
||||
*.ods binary
|
||||
*.odp binary
|
||||
*.ttf binary
|
||||
*.zim binary
|
||||
*.zim* binary
|
||||
*.eot binary
|
||||
*.svg binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
*.deb binary
|
||||
*.wasm binary
|
@ -165,7 +165,12 @@
|
||||
<Content Include="www\js\lib\arrayFromPolyfill.js" />
|
||||
<Content Include="www\js\lib\promisePolyfill.js" />
|
||||
<Content Include="www\js\lib\webpHeroBundle_0.0.0-dev.27.js" />
|
||||
<Content Include="www\js\lib\zstddec.js" />
|
||||
<Content Include="www\js\lib\xzdec-asm.js" />
|
||||
<Content Include="www\js\lib\xzdec-wasm.js" />
|
||||
<Content Include="www\js\lib\xzdec-wasm.wasm" />
|
||||
<Content Include="www\js\lib\zstddec-asm.js" />
|
||||
<Content Include="www\js\lib\zstddec-wasm.js" />
|
||||
<Content Include="www\js\lib\zstddec-wasm.wasm" />
|
||||
<Content Include="www\js\lib\zstddec_wrapper.js" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
<None Include="kiwix.pfx" />
|
||||
@ -316,7 +321,6 @@
|
||||
<Content Include="www\js\lib\uiUtil.js" />
|
||||
<Content Include="www\js\lib\utf8.js" />
|
||||
<Content Include="www\js\lib\util.js" />
|
||||
<Content Include="www\js\lib\xzdec.js" />
|
||||
<Content Include="www\js\lib\xzdec_wrapper.js" />
|
||||
<Content Include="www\js\lib\zimArchive.js" />
|
||||
<Content Include="www\js\lib\zimArchiveLoader.js" />
|
||||
|
@ -15,7 +15,7 @@ const regexpKiwixDownloadLinks = /download\.kiwix\.org/i;
|
||||
const regexpZIMUrlWithNamespace = /(?:^|\/)([^\/]+\/)([-ABCIJMUVWX])\/(.+)/;
|
||||
|
||||
const CACHE = "kiwix-precache-" + appVersion;
|
||||
const precacheFiles = [
|
||||
let precacheFiles = [
|
||||
".",
|
||||
"www",
|
||||
"www/",
|
||||
@ -68,16 +68,14 @@ const precacheFiles = [
|
||||
"www/js/lib/images.js",
|
||||
"www/js/lib/jquery-3.2.1.slim.js",
|
||||
"www/js/lib/kiwixServe.js",
|
||||
"www/js/lib/promisPolyfill.js",
|
||||
"www/js/lib/promisePolyfill.js",
|
||||
"www/js/lib/require.js",
|
||||
"www/js/lib/settingsStore.js",
|
||||
"www/js/lib/transformStyles.js",
|
||||
"www/js/lib/uiUtil.js",
|
||||
"www/js/lib/utf8.js",
|
||||
"www/js/lib/util.js",
|
||||
"www/js/lib/xzdec.js",
|
||||
"www/js/lib/xzdec_wrapper.js",
|
||||
"www/js/lib/zstddec.js",
|
||||
"www/js/lib/zstddec_wrapper.js",
|
||||
"www/js/lib/zimArchive.js",
|
||||
"www/js/lib/zimArchiveLoader.js",
|
||||
@ -95,6 +93,20 @@ const precacheFiles = [
|
||||
"www/js/katex/fonts/KaTeX_Size4-Regular.woff2"
|
||||
];
|
||||
|
||||
if ('WebAssembly' in self) {
|
||||
precacheFiles.push(
|
||||
"www/js/lib/xzdec-wasm.js",
|
||||
"www/js/lib/xzdec-wasm.wasm",
|
||||
"www/js/lib/zstddec-wasm.js",
|
||||
"www/js/lib/zstddec-wasm.wasm"
|
||||
);
|
||||
} else {
|
||||
precacheFiles.push(
|
||||
"www/js/lib/xzdec-asm.js",
|
||||
"www/js/lib/zstddec-asm.js"
|
||||
);
|
||||
}
|
||||
|
||||
// DEV: add any URL schemata that should be excluded from caching with the Cache API to the regex below
|
||||
// As of 08-2019 the chrome-extension: schema is incompatible with the Cache API
|
||||
// 'example-extension' is included to show how to add another schema if necessary
|
||||
|
@ -433,13 +433,21 @@ require.config({
|
||||
}
|
||||
});
|
||||
|
||||
requirejs(['bootstrap', 'promisePolyfill', 'arrayFromPolyfill'], function () {
|
||||
var req = ['bootstrap']; // Baseline Require array
|
||||
|
||||
// Add polyfills to the Require array only if needed
|
||||
if (!('Promise' in self)) req.push('promisePolyfill');
|
||||
if (!('from' in Array)) req.push('arrayFromPolyfill');
|
||||
|
||||
requirejs(req, function () {
|
||||
requirejs(['../app']);
|
||||
});
|
||||
|
||||
// Load the WebP Polyfills only if needed
|
||||
// Test if WebP is natively supported, and if not, set webpMachine to true. The value of webpMachine
|
||||
// will determine whether the WebP Polyfills will be loaded (currently only used in uiUtil.js)
|
||||
var webpMachine = false;
|
||||
// Using self-invoking function to avoid defining global functions and variables
|
||||
|
||||
// We use a self-invoking function here to avoid defining unnecessary global functions and variables
|
||||
(function (callback) {
|
||||
// Tests for native WebP support
|
||||
var webP = new Image();
|
||||
|
@ -25,7 +25,7 @@
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
'use strict';
|
||||
define(['jquery'], function(jQuery) {
|
||||
define([], function() {
|
||||
|
||||
/**
|
||||
* Storage implemented by Firefox OS
|
||||
@ -50,11 +50,12 @@ define(['jquery'], function(jQuery) {
|
||||
* rejected with an error message.
|
||||
*/
|
||||
StorageFirefoxOS.prototype.get = function(path) {
|
||||
var deferred = q.defer();
|
||||
var request = this._storage.get(path);
|
||||
request.onsuccess = function() { deferred.resolve(this.result); };
|
||||
request.onerror = function() { deferred.reject(this.error.name); };
|
||||
return deferred.promise;
|
||||
var that = this;
|
||||
return new Promise(function (resolve, reject){
|
||||
var request = that._storage.get(path);
|
||||
request.onsuccess = function() { resolve(this.result); };
|
||||
request.onerror = function() { reject(this.error.name); };
|
||||
});
|
||||
};
|
||||
|
||||
// We try to match both a standalone ZIM file (.zim) or
|
||||
@ -67,15 +68,16 @@ define(['jquery'], function(jQuery) {
|
||||
* paths and rejected with an error message.
|
||||
*/
|
||||
StorageFirefoxOS.prototype.scanForArchives = function() {
|
||||
var deferred = jQuery.Deferred();
|
||||
var that = this;
|
||||
return new Promise(function (resolve, reject){
|
||||
var directories = [];
|
||||
var cursor = this._storage.enumerate();
|
||||
var cursor = that._storage.enumerate();
|
||||
cursor.onerror = function() {
|
||||
deferred.reject(cursor.error);
|
||||
reject(cursor.error);
|
||||
};
|
||||
cursor.onsuccess = function() {
|
||||
if (!cursor.result) {
|
||||
deferred.resolve(directories);
|
||||
resolve(directories);
|
||||
return;
|
||||
}
|
||||
var file = cursor.result;
|
||||
@ -86,7 +88,7 @@ define(['jquery'], function(jQuery) {
|
||||
|
||||
cursor.continue();
|
||||
};
|
||||
return deferred.promise();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,9 +1,7 @@
|
||||
/**
|
||||
* Simple Array.from polyfi8ll (with Set support) from https://stackoverflow.com/a/62682524/9727685
|
||||
* Simple Array.from polyfill (with Set support) from https://stackoverflow.com/a/62682524/9727685
|
||||
*/
|
||||
(function () {
|
||||
// Detection
|
||||
if ('from' in Array) return;
|
||||
|
||||
function arrayFrom(arr, callbackFn, thisArg) {
|
||||
//if you need you can uncomment the following line
|
||||
@ -31,5 +29,5 @@
|
||||
return arNew;
|
||||
}
|
||||
//You could also use it without the following line, but it is not recommended because native function is faster.
|
||||
Array.from = arrayFrom; //We set it as polyfill
|
||||
Array.from = Array.from || arrayFrom; //We set it as polyfill
|
||||
}());
|
@ -22,6 +22,7 @@
|
||||
* along with Kiwix JS (file LICENSE). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
define([], function() {
|
||||
/**
|
||||
* Set maximum number of cache blocks of BLOCK_SIZE bytes each
|
||||
@ -117,7 +118,6 @@ define([], function() {
|
||||
var cache = new LRUCache();
|
||||
|
||||
/** CACHE TUNING **/
|
||||
|
||||
// DEV: Uncomment this block and blocks below marked 'CACHE TUNING' to measure Cache hit and miss rates for different Cache sizes
|
||||
// var hits = 0;
|
||||
// var misses = 0;
|
||||
|
@ -12,8 +12,6 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if ('Promise' in self) return;
|
||||
|
||||
var $undefined
|
||||
, $null = null
|
||||
, isBrowser = typeof self === 'object'
|
||||
|
54
www/js/lib/xzdec-asm.js
Normal file
54
www/js/lib/xzdec-asm.js
Normal file
File diff suppressed because one or more lines are too long
32
www/js/lib/xzdec-wasm.js
Normal file
32
www/js/lib/xzdec-wasm.js
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
var XZ = (function () {
|
||||
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
|
||||
|
||||
return (
|
||||
function(XZ) {
|
||||
XZ = XZ || {};
|
||||
|
||||
|
||||
var a;a||(a=typeof XZ !== 'undefined' ? XZ : {});var e,f;a.ready=new Promise(function(b,c){e=b;f=c});var h={},k;for(k in a)a.hasOwnProperty(k)&&(h[k]=a[k]);var m="";"undefined"!==typeof document&&document.currentScript&&(m=document.currentScript.src);_scriptDir&&(m=_scriptDir);0!==m.indexOf("blob:")?m=m.substr(0,m.lastIndexOf("/")+1):m="";var n=a.printErr||console.warn.bind(console);for(k in h)h.hasOwnProperty(k)&&(a[k]=h[k]);h=null;var p;a.wasmBinary&&(p=a.wasmBinary);
|
||||
var noExitRuntime=a.noExitRuntime||!0;"object"!==typeof WebAssembly&&q("no native wasm support detected");var r,t=!1,u,v,w=[],x=[],z=[];function A(){var b=a.preRun.shift();w.unshift(b)}var B=0,C=null,D=null;a.preloadedImages={};a.preloadedAudios={};function q(b){if(a.onAbort)a.onAbort(b);n(b);t=!0;b=new WebAssembly.RuntimeError("abort("+b+"). Build with -s ASSERTIONS=1 for more info.");f(b);throw b;}function E(){return F.startsWith("data:application/octet-stream;base64,")}var F;F="xzdec-wasm.wasm";
|
||||
if(!E()){var G=F;F=a.locateFile?a.locateFile(G,m):m+G}function H(){var b=F;try{if(b==F&&p)return new Uint8Array(p);throw"both async and sync fetching of the wasm failed";}catch(c){q(c)}}function I(){return p||"function"!==typeof fetch?Promise.resolve().then(function(){return H()}):fetch(F,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+F+"'";return b.arrayBuffer()}).catch(function(){return H()})}
|
||||
function J(b){for(;0<b.length;){var c=b.shift();if("function"==typeof c)c(a);else{var g=c.u;"number"===typeof g?void 0===c.s?v.get(g)():v.get(g)(c.s):g(void 0===c.s?null:c.s)}}}var K={a:function(b,c,g){u.copyWithin(b,c,c+g)},b:function(){q("OOM")}};
|
||||
(function(){function b(d){a.asm=d.exports;r=a.asm.c;d=r.buffer;a.HEAP8=new Int8Array(d);a.HEAP16=new Int16Array(d);a.HEAP32=new Int32Array(d);a.HEAPU8=u=new Uint8Array(d);a.HEAPU16=new Uint16Array(d);a.HEAPU32=new Uint32Array(d);a.HEAPF32=new Float32Array(d);a.HEAPF64=new Float64Array(d);v=a.asm.o;x.unshift(a.asm.d);B--;a.monitorRunDependencies&&a.monitorRunDependencies(B);0==B&&(null!==C&&(clearInterval(C),C=null),D&&(d=D,D=null,d()))}function c(d){b(d.instance)}function g(d){return I().then(function(l){return WebAssembly.instantiate(l,
|
||||
y)}).then(d,function(l){n("failed to asynchronously prepare wasm: "+l);q(l)})}var y={a:K};B++;a.monitorRunDependencies&&a.monitorRunDependencies(B);if(a.instantiateWasm)try{return a.instantiateWasm(y,b)}catch(d){return n("Module.instantiateWasm callback failed with error: "+d),!1}(function(){return p||"function"!==typeof WebAssembly.instantiateStreaming||E()||"function"!==typeof fetch?g(c):fetch(F,{credentials:"same-origin"}).then(function(d){return WebAssembly.instantiateStreaming(d,y).then(c,function(l){n("wasm streaming compile failed: "+
|
||||
l);n("falling back to ArrayBuffer instantiation");return g(c)})})})().catch(f);return{}})();a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.d).apply(null,arguments)};a._init=function(){return(a._init=a.asm.e).apply(null,arguments)};a._init_decompression=function(){return(a._init_decompression=a.asm.f).apply(null,arguments)};a._input_empty=function(){return(a._input_empty=a.asm.g).apply(null,arguments)};a._get_in_buffer=function(){return(a._get_in_buffer=a.asm.h).apply(null,arguments)};
|
||||
a._set_new_input=function(){return(a._set_new_input=a.asm.i).apply(null,arguments)};a._decompress=function(){return(a._decompress=a.asm.j).apply(null,arguments)};a._get_out_pos=function(){return(a._get_out_pos=a.asm.k).apply(null,arguments)};a._get_out_buffer=function(){return(a._get_out_buffer=a.asm.l).apply(null,arguments)};a._out_buffer_cleared=function(){return(a._out_buffer_cleared=a.asm.m).apply(null,arguments)};a._release=function(){return(a._release=a.asm.n).apply(null,arguments)};var L;
|
||||
D=function M(){L||N();L||(D=M)};
|
||||
function N(){function b(){if(!L&&(L=!0,a.calledRun=!0,!t)){J(x);e(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var c=a.postRun.shift();z.unshift(c)}J(z)}}if(!(0<B)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)A();J(w);0<B||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}a.run=N;
|
||||
if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();N();
|
||||
|
||||
|
||||
return XZ.ready
|
||||
}
|
||||
);
|
||||
})();
|
||||
if (typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = XZ;
|
||||
else if (typeof define === 'function' && define['amd'])
|
||||
define([], function() { return XZ; });
|
||||
else if (typeof exports === 'object')
|
||||
exports["XZ"] = XZ;
|
BIN
www/js/lib/xzdec-wasm.wasm
Normal file
BIN
www/js/lib/xzdec-wasm.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* xzdec_wrapper.js: Javascript wrapper around compiled xz decompressor.
|
||||
*
|
||||
* Copyright 2015 Mossroy and contributors
|
||||
* Copyright 2021 Mossroy and contributors
|
||||
* License GPL v3:
|
||||
*
|
||||
* This file is part of Kiwix.
|
||||
@ -20,10 +20,55 @@
|
||||
* 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();
|
||||
|
||||
// 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
|
||||
// because they cannot interpret WebAssembly.
|
||||
var rqDefXZ = [];
|
||||
|
||||
// Select asm or wasm conditionally
|
||||
if ('WebAssembly' in self) {
|
||||
console.debug('Using WASM xz decoder');
|
||||
rqDefXZ.push('xzdec-wasm');
|
||||
} else {
|
||||
console.debug('Using ASM xz decoder');
|
||||
rqDefXZ.push('xzdec-asm');
|
||||
}
|
||||
|
||||
define(rqDefXZ, function() {
|
||||
// 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
|
||||
// There is no longer any need to load it in index.html
|
||||
// For explanation of loading method below to avoid conflicts, see https://github.com/emscripten-core/emscripten/blob/master/src/settings.js
|
||||
|
||||
/**
|
||||
* @typedef EMSInstance An object type representing an Emscripten instance
|
||||
*/
|
||||
|
||||
/**
|
||||
* The XZ Decoder instance
|
||||
* @type EMSInstance
|
||||
*/
|
||||
var xzdec;
|
||||
|
||||
var instantiateDecoder = function (instance) {
|
||||
xzdec = instance;
|
||||
};
|
||||
|
||||
XZ().then(instantiateDecoder)
|
||||
.catch(function (err) {
|
||||
console.debug(err);
|
||||
if (/CompileError.+?WASM/i.test(err.message)) {
|
||||
console.log("WASM failed to load, falling back to ASM...", err);
|
||||
XZ = null;
|
||||
require(['xzdec-asm'], function() {
|
||||
XZ().then(instantiateDecoder)
|
||||
.catch(function (err) {
|
||||
console.error('Could not instantiate any decoder!', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Number of milliseconds to wait for the decompressor to be available for another chunk
|
||||
@ -86,6 +131,7 @@ define(['xzdec'], function() {
|
||||
* @returns {Promise} A Promise for the read data
|
||||
*/
|
||||
Decompressor.prototype.readSliceSingleThread = function(offset, length) {
|
||||
// Tests whether the decompressor is ready (initiated) and not busy
|
||||
if (xzdec && !busy) {
|
||||
return this.readSlice(offset, length);
|
||||
} else {
|
||||
@ -94,7 +140,6 @@ define(['xzdec'], function() {
|
||||
// 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);
|
||||
@ -149,7 +194,6 @@ define(['xzdec'], function() {
|
||||
*/
|
||||
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;
|
||||
|
@ -20,6 +20,21 @@
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Add Polyfill currently required by IE11 to run zstddec-asm and xzdec-asm
|
||||
* See https://github.com/emscripten-core/emscripten/issues/14700
|
||||
* If this is resolved upstream, remove this polyfill
|
||||
*/
|
||||
if (!String.prototype.startsWith) {
|
||||
Object.defineProperty(String.prototype, 'startsWith', {
|
||||
value: function(search, rawPos) {
|
||||
var pos = rawPos > 0 ? rawPos|0 : 0;
|
||||
return this.substring(pos, pos + search.length) === search;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
define(['xzdec_wrapper', 'zstddec_wrapper', 'util', 'utf8', 'zimDirEntry', 'filecache'], function(xz, zstd, util, utf8, zimDirEntry, FileCache) {
|
||||
|
||||
/**
|
||||
|
58
www/js/lib/zstddec-asm.js
Normal file
58
www/js/lib/zstddec-asm.js
Normal file
File diff suppressed because one or more lines are too long
36
www/js/lib/zstddec-wasm.js
Normal file
36
www/js/lib/zstddec-wasm.js
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
var ZD = (function() {
|
||||
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
|
||||
|
||||
return (
|
||||
function(ZD) {
|
||||
ZD = ZD || {};
|
||||
|
||||
|
||||
var a;a||(a=typeof ZD !== 'undefined' ? ZD : {});var q,r;a.ready=new Promise(function(b,c){q=b;r=c});var t={},w;for(w in a)a.hasOwnProperty(w)&&(t[w]=a[w]);var x="";"undefined"!==typeof document&&document.currentScript&&(x=document.currentScript.src);_scriptDir&&(x=_scriptDir);0!==x.indexOf("blob:")?x=x.substr(0,x.lastIndexOf("/")+1):x="";var y=a.printErr||console.warn.bind(console);for(w in t)t.hasOwnProperty(w)&&(a[w]=t[w]);t=null;var z;a.wasmBinary&&(z=a.wasmBinary);
|
||||
var noExitRuntime=a.noExitRuntime||!0;"object"!==typeof WebAssembly&&A("no native wasm support detected");var B,C=!1;function D(b){var c=a["_"+b];c||A("Assertion failed: Cannot call unknown function "+(b+", make sure it is exported"));return c}
|
||||
function aa(b,c,g,n){var e={string:function(d){var m=0;if(null!==d&&void 0!==d&&0!==d){var l=(d.length<<2)+1;m=E(l);var h=m,f=F;if(0<l){l=h+l-1;for(var u=0;u<d.length;++u){var k=d.charCodeAt(u);if(55296<=k&&57343>=k){var ba=d.charCodeAt(++u);k=65536+((k&1023)<<10)|ba&1023}if(127>=k){if(h>=l)break;f[h++]=k}else{if(2047>=k){if(h+1>=l)break;f[h++]=192|k>>6}else{if(65535>=k){if(h+2>=l)break;f[h++]=224|k>>12}else{if(h+3>=l)break;f[h++]=240|k>>18;f[h++]=128|k>>12&63}f[h++]=128|k>>6&63}f[h++]=128|k&63}}f[h]=
|
||||
0}}return m},array:function(d){var m=E(d.length);H.set(d,m);return m}},p=D(b),G=[];b=0;if(n)for(var v=0;v<n.length;v++){var Q=e[g[v]];Q?(0===b&&(b=I()),G[v]=Q(n[v])):G[v]=n[v]}g=p.apply(null,G);g=function(d){if("string"===c)if(d){for(var m=F,l=d+NaN,h=d;m[h]&&!(h>=l);)++h;if(16<h-d&&m.subarray&&J)d=J.decode(m.subarray(d,h));else{for(l="";d<h;){var f=m[d++];if(f&128){var u=m[d++]&63;if(192==(f&224))l+=String.fromCharCode((f&31)<<6|u);else{var k=m[d++]&63;f=224==(f&240)?(f&15)<<12|u<<6|k:(f&7)<<18|
|
||||
u<<12|k<<6|m[d++]&63;65536>f?l+=String.fromCharCode(f):(f-=65536,l+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else l+=String.fromCharCode(f)}d=l}}else d="";else d="boolean"===c?!!d:d;return d}(g);0!==b&&K(b);return g}var J="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0,H,F,L,M=[],N=[],O=[];function ca(){var b=a.preRun.shift();M.unshift(b)}var P=0,R=null,S=null;a.preloadedImages={};a.preloadedAudios={};
|
||||
function A(b){if(a.onAbort)a.onAbort(b);y(b);C=!0;b=new WebAssembly.RuntimeError("abort("+b+"). Build with -s ASSERTIONS=1 for more info.");r(b);throw b;}function T(){return U.startsWith("data:application/octet-stream;base64,")}var U;U="zstddec-wasm.wasm";if(!T()){var V=U;U=a.locateFile?a.locateFile(V,x):x+V}function W(){var b=U;try{if(b==U&&z)return new Uint8Array(z);throw"both async and sync fetching of the wasm failed";}catch(c){A(c)}}
|
||||
function da(){return z||"function"!==typeof fetch?Promise.resolve().then(function(){return W()}):fetch(U,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+U+"'";return b.arrayBuffer()}).catch(function(){return W()})}function X(b){for(;0<b.length;){var c=b.shift();if("function"==typeof c)c(a);else{var g=c.u;"number"===typeof g?void 0===c.s?L.get(g)():L.get(g)(c.s):g(void 0===c.s?null:c.s)}}}var ea={a:function(b,c,g){F.copyWithin(b,c,c+g)},b:function(){A("OOM")}};
|
||||
(function(){function b(e){a.asm=e.exports;B=a.asm.c;e=B.buffer;a.HEAP8=H=new Int8Array(e);a.HEAP16=new Int16Array(e);a.HEAP32=new Int32Array(e);a.HEAPU8=F=new Uint8Array(e);a.HEAPU16=new Uint16Array(e);a.HEAPU32=new Uint32Array(e);a.HEAPF32=new Float32Array(e);a.HEAPF64=new Float64Array(e);L=a.asm.o;N.unshift(a.asm.d);P--;a.monitorRunDependencies&&a.monitorRunDependencies(P);0==P&&(null!==R&&(clearInterval(R),R=null),S&&(e=S,S=null,e()))}function c(e){b(e.instance)}function g(e){return da().then(function(p){return WebAssembly.instantiate(p,
|
||||
n)}).then(e,function(p){y("failed to asynchronously prepare wasm: "+p);A(p)})}var n={a:ea};P++;a.monitorRunDependencies&&a.monitorRunDependencies(P);if(a.instantiateWasm)try{return a.instantiateWasm(n,b)}catch(e){return y("Module.instantiateWasm callback failed with error: "+e),!1}(function(){return z||"function"!==typeof WebAssembly.instantiateStreaming||T()||"function"!==typeof fetch?g(c):fetch(U,{credentials:"same-origin"}).then(function(e){return WebAssembly.instantiateStreaming(e,n).then(c,function(p){y("wasm streaming compile failed: "+
|
||||
p);y("falling back to ArrayBuffer instantiation");return g(c)})})})().catch(r);return{}})();a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.d).apply(null,arguments)};a._malloc=function(){return(a._malloc=a.asm.e).apply(null,arguments)};a._free=function(){return(a._free=a.asm.f).apply(null,arguments)};a._ZSTD_isError=function(){return(a._ZSTD_isError=a.asm.g).apply(null,arguments)};a._ZSTD_getErrorName=function(){return(a._ZSTD_getErrorName=a.asm.h).apply(null,arguments)};
|
||||
a._ZSTD_createDStream=function(){return(a._ZSTD_createDStream=a.asm.i).apply(null,arguments)};a._ZSTD_freeDStream=function(){return(a._ZSTD_freeDStream=a.asm.j).apply(null,arguments)};a._ZSTD_DStreamInSize=function(){return(a._ZSTD_DStreamInSize=a.asm.k).apply(null,arguments)};a._ZSTD_DStreamOutSize=function(){return(a._ZSTD_DStreamOutSize=a.asm.l).apply(null,arguments)};a._ZSTD_initDStream=function(){return(a._ZSTD_initDStream=a.asm.m).apply(null,arguments)};
|
||||
a._ZSTD_decompressStream=function(){return(a._ZSTD_decompressStream=a.asm.n).apply(null,arguments)};var I=a.stackSave=function(){return(I=a.stackSave=a.asm.p).apply(null,arguments)},K=a.stackRestore=function(){return(K=a.stackRestore=a.asm.q).apply(null,arguments)},E=a.stackAlloc=function(){return(E=a.stackAlloc=a.asm.r).apply(null,arguments)};a.cwrap=function(b,c,g,n){g=g||[];var e=g.every(function(p){return"number"===p});return"string"!==c&&e&&!n?D(b):function(){return aa(b,c,g,arguments)}};var Y;
|
||||
S=function fa(){Y||Z();Y||(S=fa)};
|
||||
function Z(){function b(){if(!Y&&(Y=!0,a.calledRun=!0,!C)){X(N);q(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var c=a.postRun.shift();O.unshift(c)}X(O)}}if(!(0<P)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)ca();X(M);0<P||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}a.run=Z;
|
||||
if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();Z();
|
||||
|
||||
|
||||
return ZD.ready
|
||||
}
|
||||
);
|
||||
})();
|
||||
if (typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = ZD;
|
||||
else if (typeof define === 'function' && define['amd'])
|
||||
define([], function() { return ZD; });
|
||||
else if (typeof exports === 'object')
|
||||
exports["ZD"] = ZD;
|
BIN
www/js/lib/zstddec-wasm.wasm
Normal file
BIN
www/js/lib/zstddec-wasm.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -20,10 +20,24 @@
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
'use strict';
|
||||
define(['zstddec'], function() {
|
||||
// DEV: zstddec.js has been compiled with `-s EXPORT_NAME="ZD" -s MODULARIZE=1` to avoid a clash with xzdec which uses "Module" as its exported object
|
||||
// Note that we include zstddec 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
|
||||
|
||||
// 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
|
||||
// because they cannot interpret WebAssembly.
|
||||
var rqDefZD = [];
|
||||
|
||||
// Select asm or wasm conditionally
|
||||
if ('WebAssembly' in self) {
|
||||
console.debug('Using WASM zstandard decoder');
|
||||
rqDefZD.push('zstddec-wasm');
|
||||
} else {
|
||||
console.debug('Using ASM zstandard decoder');
|
||||
rqDefZD.push('zstddec-asm');
|
||||
}
|
||||
|
||||
define(rqDefZD, function() {
|
||||
// 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
|
||||
// For explanation of loading method below to avoid conflicts, see https://github.com/emscripten-core/emscripten/blob/master/src/settings.js
|
||||
|
||||
/**
|
||||
@ -39,7 +53,8 @@ define(['zstddec'], function() {
|
||||
* @type EMSInstanceExt
|
||||
*/
|
||||
var zd;
|
||||
ZD().then(function(instance) {
|
||||
|
||||
var instantiateDecoder = function (instance) {
|
||||
// Instantiate the zd object
|
||||
zd = instance;
|
||||
// Create JS API by wrapping C++ functions
|
||||
@ -82,6 +97,21 @@ define(['zstddec'], function() {
|
||||
zd._outBuffer.ptr = mallocOrDie(3 << 2); // 3 x 32bit bytes
|
||||
// Reserve w/asm memory for the outBuffer data steam
|
||||
zd._outBuffer.dst = mallocOrDie(zd._outBuffer.size);
|
||||
};
|
||||
|
||||
ZD().then(instantiateDecoder)
|
||||
.catch(function (err) {
|
||||
console.debug(err);
|
||||
if (/CompileError.+?WASM/i.test(err.message)) {
|
||||
console.log("WASM failed to load, falling back to ASM...", err);
|
||||
ZD = null;
|
||||
require(['zstddec-asm'], function() {
|
||||
ZD().then(instantiateDecoder)
|
||||
.catch(function (err) {
|
||||
console.error('Could not instantiate any decoder!', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@ -94,7 +124,7 @@ define(['zstddec'], function() {
|
||||
* Is the decompressor already working?
|
||||
* @type Boolean
|
||||
*/
|
||||
appstate.zdBusy = false;
|
||||
var busy = false;
|
||||
|
||||
/**
|
||||
* @typedef Decompressor
|
||||
@ -113,6 +143,7 @@ define(['zstddec'], function() {
|
||||
function Decompressor(reader) {
|
||||
this._reader = reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the decompression stream, and initiate a read loop to decompress from the beginning of the cluster
|
||||
* until we reach <offset> in the decompressed byte stream
|
||||
@ -121,7 +152,7 @@ define(['zstddec'], function() {
|
||||
* @returns {Promise<ArrayBuffer>} Promise for an ArrayBuffer with decoded data
|
||||
*/
|
||||
Decompressor.prototype.readSlice = function(offset, length) {
|
||||
appstate.zdBusy = true;
|
||||
busy = true;
|
||||
this._inStreamPos = 0;
|
||||
this._inStreamChunkedPos = 0;
|
||||
this._outStreamPos = 0;
|
||||
@ -139,7 +170,7 @@ define(['zstddec'], function() {
|
||||
// Should you need to free the decoder stream handle, use command below, but be sure to create a new stream control object
|
||||
// before attempting further decompression
|
||||
// zd._ZSTD_freeDStream(zd._decHandle);
|
||||
appstate.zdBusy = false;
|
||||
busy = false;
|
||||
return data;
|
||||
});
|
||||
};
|
||||
@ -152,7 +183,8 @@ define(['zstddec'], function() {
|
||||
* @returns {Promise} A Promise for the readSlice() function
|
||||
*/
|
||||
Decompressor.prototype.readSliceSingleThread = function (offset, length) {
|
||||
if (zd && !appstate.zdBusy) {
|
||||
// Tests whether the decompressor is ready (initiated) and not busy
|
||||
if (zd && !busy) {
|
||||
return this.readSlice(offset, length);
|
||||
} else {
|
||||
// The decompressor is already in progress.
|
||||
|
Loading…
x
Reference in New Issue
Block a user