Convert HNTrie code to ES6 class

This commit is contained in:
Raymond Hill 2019-04-25 19:38:07 -04:00
parent 155abfba18
commit e0d2285da0
No known key found for this signature in database
GPG key ID: 25E1490B761470C2

View file

@ -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'