mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-13 10:17:34 +01:00
Convert HNTrie code to ES6 class
This commit is contained in:
parent
155abfba18
commit
e0d2285da0
1 changed files with 95 additions and 89 deletions
184
src/js/hntrie.js
184
src/js/hntrie.js
|
@ -123,43 +123,42 @@ const HNTRIE_CHAR0_SLOT = HNTRIE_TRIE0_SLOT + 2; // 66 / 264
|
||||||
const HNTRIE_CHAR1_SLOT = HNTRIE_TRIE0_SLOT + 3; // 67 / 268
|
const HNTRIE_CHAR1_SLOT = HNTRIE_TRIE0_SLOT + 3; // 67 / 268
|
||||||
const HNTRIE_TRIE0_START = HNTRIE_TRIE0_SLOT + 4 << 2; // 272
|
const HNTRIE_TRIE0_START = HNTRIE_TRIE0_SLOT + 4 << 2; // 272
|
||||||
|
|
||||||
|
const HNTrieContainer = class {
|
||||||
|
|
||||||
const HNTrieContainer = function(details) {
|
constructor(details) {
|
||||||
if ( details instanceof Object === false ) { details = {}; }
|
if ( details instanceof Object === false ) { details = {}; }
|
||||||
let len = (details.byteLength || 0) + HNTRIE_PAGE_SIZE-1 & ~(HNTRIE_PAGE_SIZE-1);
|
let len = (details.byteLength || 0) + HNTRIE_PAGE_SIZE-1 & ~(HNTRIE_PAGE_SIZE-1);
|
||||||
this.buf = new Uint8Array(Math.max(len, 131072));
|
this.buf = new Uint8Array(Math.max(len, 131072));
|
||||||
this.buf32 = new Uint32Array(this.buf.buffer);
|
this.buf32 = new Uint32Array(this.buf.buffer);
|
||||||
this.needle = '';
|
this.needle = '';
|
||||||
this.buf32[HNTRIE_TRIE0_SLOT] = HNTRIE_TRIE0_START;
|
this.buf32[HNTRIE_TRIE0_SLOT] = HNTRIE_TRIE0_START;
|
||||||
this.buf32[HNTRIE_TRIE1_SLOT] = this.buf32[HNTRIE_TRIE0_SLOT];
|
this.buf32[HNTRIE_TRIE1_SLOT] = this.buf32[HNTRIE_TRIE0_SLOT];
|
||||||
this.buf32[HNTRIE_CHAR0_SLOT] = details.char0 || 65536;
|
this.buf32[HNTRIE_CHAR0_SLOT] = details.char0 || 65536;
|
||||||
this.buf32[HNTRIE_CHAR1_SLOT] = this.buf32[HNTRIE_CHAR0_SLOT];
|
this.buf32[HNTRIE_CHAR1_SLOT] = this.buf32[HNTRIE_CHAR0_SLOT];
|
||||||
this.wasmInstancePromise = null;
|
this.wasmInstancePromise = null;
|
||||||
this.wasmMemory = null;
|
this.wasmMemory = null;
|
||||||
this.readyToUse();
|
this.readyToUse();
|
||||||
};
|
}
|
||||||
|
|
||||||
HNTrieContainer.prototype = {
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Public methods
|
// Public methods
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
reset: function() {
|
reset() {
|
||||||
this.buf32[HNTRIE_TRIE1_SLOT] = this.buf32[HNTRIE_TRIE0_SLOT];
|
this.buf32[HNTRIE_TRIE1_SLOT] = this.buf32[HNTRIE_TRIE0_SLOT];
|
||||||
this.buf32[HNTRIE_CHAR1_SLOT] = this.buf32[HNTRIE_CHAR0_SLOT];
|
this.buf32[HNTRIE_CHAR1_SLOT] = this.buf32[HNTRIE_CHAR0_SLOT];
|
||||||
},
|
}
|
||||||
|
|
||||||
readyToUse: function() {
|
readyToUse() {
|
||||||
if ( HNTrieContainer.wasmModulePromise instanceof Promise === false ) {
|
if ( HNTrieContainer.wasmModulePromise instanceof Promise === false ) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return HNTrieContainer.wasmModulePromise.then(
|
return HNTrieContainer.wasmModulePromise.then(
|
||||||
module => this.initWASM(module)
|
module => this.initWASM(module)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
setNeedle: function(needle) {
|
setNeedle(needle) {
|
||||||
if ( needle !== this.needle ) {
|
if ( needle !== this.needle ) {
|
||||||
const buf = this.buf;
|
const buf = this.buf;
|
||||||
let i = needle.length;
|
let i = needle.length;
|
||||||
|
@ -171,9 +170,9 @@ HNTrieContainer.prototype = {
|
||||||
this.needle = needle;
|
this.needle = needle;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
}
|
||||||
|
|
||||||
matchesJS: function(iroot) {
|
matchesJS(iroot) {
|
||||||
const char0 = this.buf32[HNTRIE_CHAR0_SLOT];
|
const char0 = this.buf32[HNTRIE_CHAR0_SLOT];
|
||||||
let ineedle = this.buf[255];
|
let ineedle = this.buf[255];
|
||||||
let icell = iroot;
|
let icell = iroot;
|
||||||
|
@ -214,11 +213,9 @@ HNTrieContainer.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ineedle === 0 || this.buf[ineedle-1] === 0x2E ? ineedle : -1;
|
return ineedle === 0 || this.buf[ineedle-1] === 0x2E ? ineedle : -1;
|
||||||
},
|
}
|
||||||
matchesWASM: null,
|
|
||||||
matches: null,
|
|
||||||
|
|
||||||
createOne: function(args) {
|
createOne(args) {
|
||||||
if ( Array.isArray(args) ) {
|
if ( Array.isArray(args) ) {
|
||||||
return new this.HNTrieRef(this, args[0], args[1]);
|
return new this.HNTrieRef(this, args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
@ -232,13 +229,13 @@ HNTrieContainer.prototype = {
|
||||||
this.buf32[iroot+1] = 0;
|
this.buf32[iroot+1] = 0;
|
||||||
this.buf32[iroot+2] = 0;
|
this.buf32[iroot+2] = 0;
|
||||||
return new this.HNTrieRef(this, iroot, 0);
|
return new this.HNTrieRef(this, iroot, 0);
|
||||||
},
|
}
|
||||||
|
|
||||||
compileOne: function(trieRef) {
|
compileOne(trieRef) {
|
||||||
return [ trieRef.iroot, trieRef.size ];
|
return [ trieRef.iroot, trieRef.size ];
|
||||||
},
|
}
|
||||||
|
|
||||||
addJS: function(iroot) {
|
addJS(iroot) {
|
||||||
let lhnchar = this.buf[255];
|
let lhnchar = this.buf[255];
|
||||||
if ( lhnchar === 0 ) { return 0; }
|
if ( lhnchar === 0 ) { return 0; }
|
||||||
let icell = iroot;
|
let icell = iroot;
|
||||||
|
@ -334,28 +331,26 @@ HNTrieContainer.prototype = {
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
addWASM: null,
|
|
||||||
add: null,
|
|
||||||
|
|
||||||
optimize: function() {
|
optimize() {
|
||||||
this.shrinkBuf();
|
this.shrinkBuf();
|
||||||
return {
|
return {
|
||||||
byteLength: this.buf.byteLength,
|
byteLength: this.buf.byteLength,
|
||||||
char0: this.buf32[HNTRIE_CHAR0_SLOT],
|
char0: this.buf32[HNTRIE_CHAR0_SLOT],
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
fromIterable: function(hostnames, add) {
|
fromIterable(hostnames, add) {
|
||||||
if ( add === undefined ) { add = 'add'; }
|
if ( add === undefined ) { add = 'add'; }
|
||||||
const trieRef = this.createOne();
|
const trieRef = this.createOne();
|
||||||
for ( const hn of hostnames ) {
|
for ( const hn of hostnames ) {
|
||||||
trieRef[add](hn);
|
trieRef[add](hn);
|
||||||
}
|
}
|
||||||
return trieRef;
|
return trieRef;
|
||||||
},
|
}
|
||||||
|
|
||||||
serialize: function(encoder) {
|
serialize(encoder) {
|
||||||
if ( encoder instanceof Object ) {
|
if ( encoder instanceof Object ) {
|
||||||
return encoder.encode(
|
return encoder.encode(
|
||||||
this.buf32.buffer,
|
this.buf32.buffer,
|
||||||
|
@ -369,9 +364,9 @@ HNTrieContainer.prototype = {
|
||||||
this.buf32[HNTRIE_CHAR1_SLOT] + 3 >>> 2
|
this.buf32[HNTRIE_CHAR1_SLOT] + 3 >>> 2
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
unserialize: function(selfie, decoder) {
|
unserialize(selfie, decoder) {
|
||||||
this.needle = '';
|
this.needle = '';
|
||||||
const shouldDecode = typeof selfie === 'string';
|
const shouldDecode = typeof selfie === 'string';
|
||||||
let byteLength = shouldDecode
|
let byteLength = shouldDecode
|
||||||
|
@ -397,25 +392,13 @@ HNTrieContainer.prototype = {
|
||||||
this.buf32.set(selfie);
|
this.buf32.set(selfie);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// Class to hold reference to a specific trie
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
HNTrieRef: function(container, iroot, size) {
|
|
||||||
this.container = container;
|
|
||||||
this.iroot = iroot;
|
|
||||||
this.size = size;
|
|
||||||
this.last = -1;
|
|
||||||
this.needle = '';
|
|
||||||
},
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Private methods
|
// Private methods
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
addCell: function(idown, iright, v) {
|
addCell(idown, iright, v) {
|
||||||
let icell = this.buf32[HNTRIE_TRIE1_SLOT];
|
let icell = this.buf32[HNTRIE_TRIE1_SLOT];
|
||||||
this.buf32[HNTRIE_TRIE1_SLOT] = icell + 12;
|
this.buf32[HNTRIE_TRIE1_SLOT] = icell + 12;
|
||||||
icell >>>= 2;
|
icell >>>= 2;
|
||||||
|
@ -423,9 +406,9 @@ HNTrieContainer.prototype = {
|
||||||
this.buf32[icell+1] = iright;
|
this.buf32[icell+1] = iright;
|
||||||
this.buf32[icell+2] = v;
|
this.buf32[icell+2] = v;
|
||||||
return icell;
|
return icell;
|
||||||
},
|
}
|
||||||
|
|
||||||
addSegment: function(lsegchar) {
|
addSegment(lsegchar) {
|
||||||
if ( lsegchar === 0 ) { return 0; }
|
if ( lsegchar === 0 ) { return 0; }
|
||||||
let char1 = this.buf32[HNTRIE_CHAR1_SLOT];
|
let char1 = this.buf32[HNTRIE_CHAR1_SLOT];
|
||||||
const isegchar = char1 - this.buf32[HNTRIE_CHAR0_SLOT];
|
const isegchar = char1 - this.buf32[HNTRIE_CHAR0_SLOT];
|
||||||
|
@ -435,9 +418,9 @@ HNTrieContainer.prototype = {
|
||||||
} while ( i !== 0 );
|
} while ( i !== 0 );
|
||||||
this.buf32[HNTRIE_CHAR1_SLOT] = char1;
|
this.buf32[HNTRIE_CHAR1_SLOT] = char1;
|
||||||
return (lsegchar << 24) | isegchar;
|
return (lsegchar << 24) | isegchar;
|
||||||
},
|
}
|
||||||
|
|
||||||
growBuf: function(trieGrow, charGrow) {
|
growBuf(trieGrow, charGrow) {
|
||||||
const char0 = Math.max(
|
const char0 = Math.max(
|
||||||
(this.buf32[HNTRIE_TRIE1_SLOT] + trieGrow + HNTRIE_PAGE_SIZE-1) & ~(HNTRIE_PAGE_SIZE-1),
|
(this.buf32[HNTRIE_TRIE1_SLOT] + trieGrow + HNTRIE_PAGE_SIZE-1) & ~(HNTRIE_PAGE_SIZE-1),
|
||||||
this.buf32[HNTRIE_CHAR0_SLOT]
|
this.buf32[HNTRIE_CHAR0_SLOT]
|
||||||
|
@ -448,18 +431,18 @@ HNTrieContainer.prototype = {
|
||||||
this.buf.length
|
this.buf.length
|
||||||
);
|
);
|
||||||
this.resizeBuf(bufLen, char0);
|
this.resizeBuf(bufLen, char0);
|
||||||
},
|
}
|
||||||
|
|
||||||
shrinkBuf: function() {
|
shrinkBuf() {
|
||||||
// Can't shrink WebAssembly.Memory
|
// Can't shrink WebAssembly.Memory
|
||||||
if ( this.wasmMemory !== null ) { return; }
|
if ( this.wasmMemory !== null ) { return; }
|
||||||
const char0 = this.buf32[HNTRIE_TRIE1_SLOT] + 24;
|
const char0 = this.buf32[HNTRIE_TRIE1_SLOT] + 24;
|
||||||
const char1 = char0 + this.buf32[HNTRIE_CHAR1_SLOT] - this.buf32[HNTRIE_CHAR0_SLOT];
|
const char1 = char0 + this.buf32[HNTRIE_CHAR1_SLOT] - this.buf32[HNTRIE_CHAR0_SLOT];
|
||||||
const bufLen = char1 + 256;
|
const bufLen = char1 + 256;
|
||||||
this.resizeBuf(bufLen, char0);
|
this.resizeBuf(bufLen, char0);
|
||||||
},
|
}
|
||||||
|
|
||||||
resizeBuf: function(bufLen, char0) {
|
resizeBuf(bufLen, char0) {
|
||||||
bufLen = bufLen + HNTRIE_PAGE_SIZE-1 & ~(HNTRIE_PAGE_SIZE-1);
|
bufLen = bufLen + HNTRIE_PAGE_SIZE-1 & ~(HNTRIE_PAGE_SIZE-1);
|
||||||
if (
|
if (
|
||||||
bufLen === this.buf.length &&
|
bufLen === this.buf.length &&
|
||||||
|
@ -510,9 +493,9 @@ HNTrieContainer.prototype = {
|
||||||
this.buf32[HNTRIE_CHAR0_SLOT] = char0;
|
this.buf32[HNTRIE_CHAR0_SLOT] = char0;
|
||||||
this.buf32[HNTRIE_CHAR1_SLOT] = char0 + charDataLen;
|
this.buf32[HNTRIE_CHAR1_SLOT] = char0 + charDataLen;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
initWASM: function(module) {
|
initWASM(module) {
|
||||||
if ( module instanceof WebAssembly.Module === false ) {
|
if ( module instanceof WebAssembly.Module === false ) {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
@ -529,9 +512,10 @@ HNTrieContainer.prototype = {
|
||||||
);
|
);
|
||||||
this.wasmInstancePromise.then(instance => {
|
this.wasmInstancePromise.then(instance => {
|
||||||
this.wasmMemory = memory;
|
this.wasmMemory = memory;
|
||||||
const pageCount = this.buf.byteLength + HNTRIE_PAGE_SIZE-1 >>> 16;
|
const curPageCount = memory.buffer.byteLength >>> 16;
|
||||||
if ( pageCount > 1 ) {
|
const newPageCount = this.buf.byteLength + HNTRIE_PAGE_SIZE-1 >>> 16;
|
||||||
memory.grow(pageCount - 1);
|
if ( newPageCount > curPageCount ) {
|
||||||
|
memory.grow(newPageCount - curPageCount);
|
||||||
}
|
}
|
||||||
const buf = new Uint8Array(memory.buffer);
|
const buf = new Uint8Array(memory.buffer);
|
||||||
buf.set(this.buf);
|
buf.set(this.buf);
|
||||||
|
@ -542,13 +526,30 @@ HNTrieContainer.prototype = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this.wasmInstancePromise;
|
return this.wasmInstancePromise;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
HNTrieContainer.prototype.matches = HNTrieContainer.prototype.matchesJS;
|
||||||
|
HNTrieContainer.prototype.matchesWASM = null;
|
||||||
|
|
||||||
HNTrieContainer.prototype.HNTrieRef.prototype = {
|
HNTrieContainer.prototype.add = HNTrieContainer.prototype.addJS;
|
||||||
add: function(hn) {
|
HNTrieContainer.prototype.addWASM = null;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Class to hold reference to a specific trie
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
HNTrieContainer.prototype.HNTrieRef = class {
|
||||||
|
|
||||||
|
constructor(container, iroot, size) {
|
||||||
|
this.container = container;
|
||||||
|
this.iroot = iroot;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(hn) {
|
||||||
if ( this.container.setNeedle(hn).add(this.iroot) === 1 ) {
|
if ( this.container.setNeedle(hn).add(this.iroot) === 1 ) {
|
||||||
this.last = -1;
|
this.last = -1;
|
||||||
this.needle = '';
|
this.needle = '';
|
||||||
|
@ -556,8 +557,9 @@ HNTrieContainer.prototype.HNTrieRef.prototype = {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
addJS: function(hn) {
|
|
||||||
|
addJS(hn) {
|
||||||
if ( this.container.setNeedle(hn).addJS(this.iroot) === 1 ) {
|
if ( this.container.setNeedle(hn).addJS(this.iroot) === 1 ) {
|
||||||
this.last = -1;
|
this.last = -1;
|
||||||
this.needle = '';
|
this.needle = '';
|
||||||
|
@ -565,8 +567,9 @@ HNTrieContainer.prototype.HNTrieRef.prototype = {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
addWASM: function(hn) {
|
|
||||||
|
addWASM(hn) {
|
||||||
if ( this.container.setNeedle(hn).addWASM(this.iroot) === 1 ) {
|
if ( this.container.setNeedle(hn).addWASM(this.iroot) === 1 ) {
|
||||||
this.last = -1;
|
this.last = -1;
|
||||||
this.needle = '';
|
this.needle = '';
|
||||||
|
@ -574,29 +577,33 @@ HNTrieContainer.prototype.HNTrieRef.prototype = {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
matches: function(needle) {
|
|
||||||
|
matches(needle) {
|
||||||
if ( needle !== this.needle ) {
|
if ( needle !== this.needle ) {
|
||||||
this.needle = needle;
|
this.needle = needle;
|
||||||
this.last = this.container.setNeedle(needle).matches(this.iroot);
|
this.last = this.container.setNeedle(needle).matches(this.iroot);
|
||||||
}
|
}
|
||||||
return this.last;
|
return this.last;
|
||||||
},
|
}
|
||||||
matchesJS: function(needle) {
|
|
||||||
|
matchesJS(needle) {
|
||||||
if ( needle !== this.needle ) {
|
if ( needle !== this.needle ) {
|
||||||
this.needle = needle;
|
this.needle = needle;
|
||||||
this.last = this.container.setNeedle(needle).matchesJS(this.iroot);
|
this.last = this.container.setNeedle(needle).matchesJS(this.iroot);
|
||||||
}
|
}
|
||||||
return this.last;
|
return this.last;
|
||||||
},
|
}
|
||||||
matchesWASM: function(needle) {
|
|
||||||
|
matchesWASM(needle) {
|
||||||
if ( needle !== this.needle ) {
|
if ( needle !== this.needle ) {
|
||||||
this.needle = needle;
|
this.needle = needle;
|
||||||
this.last = this.container.setNeedle(needle).matchesWASM(this.iroot);
|
this.last = this.container.setNeedle(needle).matchesWASM(this.iroot);
|
||||||
}
|
}
|
||||||
return this.last;
|
return this.last;
|
||||||
},
|
}
|
||||||
[Symbol.iterator]: function() {
|
|
||||||
|
[Symbol.iterator]() {
|
||||||
return {
|
return {
|
||||||
value: undefined,
|
value: undefined,
|
||||||
done: false,
|
done: false,
|
||||||
|
@ -646,9 +653,12 @@ HNTrieContainer.prototype.HNTrieRef.prototype = {
|
||||||
forks: [],
|
forks: [],
|
||||||
textDecoder: new TextDecoder()
|
textDecoder: new TextDecoder()
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HNTrieContainer.prototype.HNTrieRef.prototype.last = -1;
|
||||||
|
HNTrieContainer.prototype.HNTrieRef.prototype.needle = '';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Code below is to attempt to load a WASM module which implements:
|
// Code below is to attempt to load a WASM module which implements:
|
||||||
|
@ -662,10 +672,6 @@ HNTrieContainer.prototype.HNTrieRef.prototype = {
|
||||||
(function() {
|
(function() {
|
||||||
HNTrieContainer.wasmModulePromise = null;
|
HNTrieContainer.wasmModulePromise = null;
|
||||||
|
|
||||||
// Default to javascript version.
|
|
||||||
HNTrieContainer.prototype.matches = HNTrieContainer.prototype.matchesJS;
|
|
||||||
HNTrieContainer.prototype.add = HNTrieContainer.prototype.addJS;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof WebAssembly !== 'object' ||
|
typeof WebAssembly !== 'object' ||
|
||||||
typeof WebAssembly.compileStreaming !== 'function'
|
typeof WebAssembly.compileStreaming !== 'function'
|
||||||
|
|
Loading…
Reference in a new issue