Skip to content

Commit

Permalink
Fix Promise chain of WASM module load operations
Browse files Browse the repository at this point in the history
The Promise chain was not properly designed for WASM module
loading. This became apparent when removing WASM modules
from Opera build[1].

The problem was that errors thrown by fetch() -- used to
load WASM modules -- were not properly handled.

[1] Opera refuses updating uBO if there are unrecognized file
types in the package, and `.wasm`/`.wat` files are not
recognized by Opera uploader.
  • Loading branch information
gorhill committed Feb 1, 2019
1 parent 4f3aed6 commit 69c87c5
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 77 deletions.
15 changes: 9 additions & 6 deletions src/js/hntrie.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ HNTrieContainer.prototype = {
if ( HNTrieContainer.wasmModulePromise instanceof Promise === false ) {
return Promise.resolve();
}
return HNTrieContainer.wasmModulePromise.then(module => {
return this.initWASM(module);
});
return HNTrieContainer.wasmModulePromise.then(
module => this.initWASM(module)
);
},

setNeedle: function(needle) {
Expand Down Expand Up @@ -674,10 +674,13 @@ HNTrieContainer.prototype.HNTrieRef.prototype = {
workingDir = url.href;
}

HNTrieContainer.wasmModulePromise = WebAssembly.compileStreaming(
fetch(workingDir + 'wasm/hntrie.wasm')
HNTrieContainer.wasmModulePromise = fetch(
workingDir + 'wasm/hntrie.wasm',
{ mode: 'same-origin' }
).then(
WebAssembly.compileStreaming
).catch(reason => {
HNTrieContainer.wasmModulePromise = null;
console.error(reason);
console.info(reason);
});
})();
12 changes: 6 additions & 6 deletions src/js/lz4.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ let ttlCount = 0;
let ttlTimer;
let ttlDelay = 60000;

let init = function() {
const init = function() {
ttlDelay = µBlock.hiddenSettings.autoUpdateAssetFetchPeriod * 1000 + 15000;
if ( lz4CodecInstance === null ) {
return Promise.resolve(null);
Expand Down Expand Up @@ -72,7 +72,7 @@ let init = function() {
// which will cause the wasm instance to be forgotten after enough
// time elapse without the instance being used.

let destroy = function() {
const destroy = function() {
//if ( lz4CodecInstance !== undefined ) {
// console.info(
// 'uBO: freeing lz4-block-codec instance (%s KB)',
Expand All @@ -85,7 +85,7 @@ let destroy = function() {
ttlTimer = undefined;
};

let ttlManage = function(count) {
const ttlManage = function(count) {
if ( ttlTimer !== undefined ) {
clearTimeout(ttlTimer);
ttlTimer = undefined;
Expand All @@ -96,7 +96,7 @@ let ttlManage = function(count) {
ttlTimer = vAPI.setTimeout(destroy, ttlDelay);
};

let uint8ArrayFromBlob = function(key, data) {
const uint8ArrayFromBlob = function(key, data) {
if ( data instanceof Blob === false ) {
return Promise.resolve({ key, data });
}
Expand All @@ -109,7 +109,7 @@ let uint8ArrayFromBlob = function(key, data) {
});
};

let encodeValue = function(key, value) {
const encodeValue = function(key, value) {
if ( !lz4CodecInstance ) { return; }
//let t0 = window.performance.now();
if ( textEncoder === undefined ) {
Expand Down Expand Up @@ -138,7 +138,7 @@ let encodeValue = function(key, value) {
return outputArray;
};

let decodeValue = function(key, inputArray) {
const decodeValue = function(key, inputArray) {
if ( !lz4CodecInstance ) { return; }
//let t0 = window.performance.now();
if (
Expand Down
70 changes: 25 additions & 45 deletions src/lib/lz4/lz4-block-codec-any.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,46 +46,39 @@

/******************************************************************************/

let wd = (function() {
const wd = (function() {
let url = document.currentScript.src;
let match = /[^\/]+$/.exec(url);
return match !== null ?
url.slice(0, match.index) :
'';
})();

let removeScript = function(script) {
const removeScript = function(script) {
if ( !script ) { return; }
if ( script.parentNode === null ) { return; }
script.parentNode.removeChild(script);
};

let createInstanceWASM = function() {
const createInstanceWASM = function() {
if ( context.LZ4BlockWASM instanceof Function ) {
let instance = new context.LZ4BlockWASM();
return instance.init().then(( ) => { return instance; });
const instance = new context.LZ4BlockWASM();
return instance.init().then(ok => ok ? instance : null);
}
if ( context.LZ4BlockWASM === null ) {
return Promise.resolve(null);
}
return new Promise((resolve, reject) => {
let script = document.createElement('script');
return new Promise(resolve => {
const script = document.createElement('script');
script.src = wd + 'lz4-block-codec-wasm.js';
script.addEventListener('load', ( ) => {
if ( context.LZ4BlockWASM instanceof Function === false ) {
context.LZ4BlockWASM = null;
context.LZ4BlockWASM = undefined;
resolve(null);
} else {
let instance = new context.LZ4BlockWASM();
instance.init()
.then(( ) => {
resolve(instance);
})
.catch(error => {
reject(error);
});
return;
}
const instance = new context.LZ4BlockWASM();
instance.init().then(ok => { resolve(ok ? instance : null); });
});
script.addEventListener('error', ( ) => {
context.LZ4BlockWASM = null;
Expand All @@ -96,31 +89,25 @@ let createInstanceWASM = function() {
});
};

let createInstanceJS = function() {
const createInstanceJS = function() {
if ( context.LZ4BlockJS instanceof Function ) {
let instance = new context.LZ4BlockJS();
return instance.init().then(( ) => { return instance; });
const instance = new context.LZ4BlockJS();
return instance.init().then(ok => ok ? instance : null);
}
if ( context.LZ4BlockJS === null ) {
return Promise.resolve(null);
}
return new Promise((resolve, reject) => {
let script = document.createElement('script');
return new Promise(resolve => {
const script = document.createElement('script');
script.src = wd + 'lz4-block-codec-js.js';
script.addEventListener('load', ( ) => {
if ( context.LZ4BlockJS instanceof Function === false ) {
context.LZ4BlockJS = null;
resolve(null);
} else {
let instance = new context.LZ4BlockJS();
instance.init()
.then(( ) => {
resolve(instance);
})
.catch(error => {
reject(error);
});
return;
}
const instance = new context.LZ4BlockJS();
instance.init().then(ok => { resolve(ok ? instance : null); });
});
script.addEventListener('error', ( ) => {
context.LZ4BlockJS = null;
Expand All @@ -143,20 +130,13 @@ context.lz4BlockCodec = {
} else {
instantiator = createInstanceWASM || createInstanceJS;
}
return (instantiator)()
.then(instance => {
if ( instance ) { return instance; }
if ( flavor === undefined ) {
return createInstanceJS();
}
return null;
})
.catch(( ) => {
if ( flavor === undefined ) {
return createInstanceJS();
}
return null;
});
return (instantiator)().then(instance => {
if ( instance ) { return instance; }
if ( flavor === undefined ) {
return createInstanceJS();
}
return null;
});
},
reset: function() {
context.LZ4BlockWASM = undefined;
Expand Down
10 changes: 5 additions & 5 deletions src/lib/lz4/lz4-block-codec-js.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

/******************************************************************************/

let growOutputBuffer = function(instance, size) {
const growOutputBuffer = function(instance, size) {
if (
instance.outputBuffer === undefined ||
instance.outputBuffer.byteLength < size
Expand All @@ -56,13 +56,13 @@ let growOutputBuffer = function(instance, size) {
return instance.outputBuffer;
};

let encodeBound = function(size) {
const encodeBound = function(size) {
return size > 0x7E000000 ?
0 :
size + (size / 255 | 0) + 16;
};

let encodeBlock = function(instance, iBuf, oOffset) {
const encodeBlock = function(instance, iBuf, oOffset) {
let iLen = iBuf.byteLength;
if ( iLen >= 0x7E000000 ) { throw new RangeError(); }

Expand Down Expand Up @@ -183,7 +183,7 @@ let encodeBlock = function(instance, iBuf, oOffset) {
return new Uint8Array(oBuf.buffer, 0, oPos);
};

let decodeBlock = function(instance, iBuf, iOffset, oLen) {
const decodeBlock = function(instance, iBuf, iOffset, oLen) {
let iLen = iBuf.byteLength;
let oBuf = new Uint8Array(growOutputBuffer(instance, oLen), 0, oLen);
let iPos = iOffset, oPos = 0;
Expand Down Expand Up @@ -252,7 +252,7 @@ context.LZ4BlockJS = function() {
context.LZ4BlockJS.prototype = {
flavor: 'js',
init: function() {
return Promise.resolve();
return Promise.resolve(true);
},

reset: function() {
Expand Down
31 changes: 16 additions & 15 deletions src/lib/lz4/lz4-block-codec-wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@

/******************************************************************************/

let wd = (function() {
const wd = (function() {
let url = document.currentScript.src;
let match = /[^\/]+$/.exec(url);
return match !== null ?
url.slice(0, match.index) :
'';
})();

let growMemoryTo = function(wasmInstance, byteLength) {
const growMemoryTo = function(wasmInstance, byteLength) {
let lz4api = wasmInstance.exports;
let neededByteLength = lz4api.getLinearMemoryOffset() + byteLength;
let pageCountBefore = lz4api.memory.buffer.byteLength >>> 16;
Expand All @@ -67,7 +67,7 @@ let growMemoryTo = function(wasmInstance, byteLength) {
return lz4api.memory.buffer;
};

let encodeBlock = function(wasmInstance, inputArray, outputOffset) {
const encodeBlock = function(wasmInstance, inputArray, outputOffset) {
let lz4api = wasmInstance.exports;
let mem0 = lz4api.getLinearMemoryOffset();
let hashTableSize = 65536 * 4;
Expand Down Expand Up @@ -96,7 +96,7 @@ let encodeBlock = function(wasmInstance, inputArray, outputOffset) {
return outputArray;
};

let decodeBlock = function(wasmInstance, inputArray, inputOffset, outputSize) {
const decodeBlock = function(wasmInstance, inputArray, inputOffset, outputSize) {
let inputSize = inputArray.byteLength;
let lz4api = wasmInstance.exports;
let mem0 = lz4api.getLinearMemoryOffset();
Expand Down Expand Up @@ -130,24 +130,25 @@ context.LZ4BlockWASM.prototype = {
this.lz4wasmInstance = null;
}
if ( this.lz4wasmInstance === null ) {
return Promise.reject();
return Promise.resolve(false);
}
if ( this.lz4wasmInstance instanceof WebAssembly.Instance ) {
return Promise.resolve(this.lz4wasmInstance);
return Promise.resolve(true);
}
if ( this.lz4wasmInstance === undefined ) {
this.lz4wasmInstance = WebAssembly.instantiateStreaming(
fetch(wd + 'lz4-block-codec.wasm', { mode: 'same-origin' })
this.lz4wasmInstance = fetch(
wd + 'lz4-block-codec.wasm',
{ mode: 'same-origin' }
).then(
WebAssembly.instantiateStreaming
).then(result => {
this.lz4wasmInstance = undefined;
this.lz4wasmInstance = result && result.instance || null;
if ( this.lz4wasmInstance !== null ) { return this; }
return null;
});
this.lz4wasmInstance.catch(( ) => {
}).catch(reason => {
this.lz4wasmInstance = null;
return null;
});
console.info(reason);
}).then(( ) =>
this.lz4wasmInstance !== null
);
}
return this.lz4wasmInstance;
},
Expand Down
9 changes: 9 additions & 0 deletions tools/make-opera.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ rm -r $DES/_locales/mr
rm -r $DES/_locales/ta
rm -r $DES/_locales/th

# Removing WASM modules until I receive an answer from Opera people: Opera's
# uploader issue an error for hntrie.wasm and this prevents me from
# updating uBO in the Opera store. The modules are unused anyway for
# Chromium- based browsers.
rm $DES/js/wasm/*.wasm
rm $DES/js/wasm/*.wat
rm $DES/lib/lz4/*.wasm
rm $DES/lib/lz4/*.wat

echo "*** uBlock0.opera: Generating web accessible resources..."
cp -R src/web_accessible_resources $DES/
python3 tools/import-war.py $DES/
Expand Down

0 comments on commit 69c87c5

Please sign in to comment.