diff --git a/src/devtools.html b/src/devtools.html
index e52494d13..9defea07e 100644
--- a/src/devtools.html
+++ b/src/devtools.html
@@ -6,6 +6,7 @@
uBlock — Dev tools
+
@@ -30,6 +31,8 @@
+
+
diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js
index 58e215a09..f7027f8a9 100644
--- a/src/js/cosmetic-filtering.js
+++ b/src/js/cosmetic-filtering.js
@@ -1137,17 +1137,17 @@ FilterContainer.prototype.dump = function() {
` lowly.class.complex: ${this.lowlyGeneric.cl.complex.size}`,
` highly.simple: ${this.highlyGeneric.simple.dict.size}`,
` highly.complex: ${this.highlyGeneric.complex.dict.size}`,
- `lowly.id.simple: ${this.lowlyGeneric.id.simple.size}`,
+ `+ lowly.id.simple: ${this.lowlyGeneric.id.simple.size}`,
...Array.from(this.lowlyGeneric.id.simple).map(a => ` ###${a}`),
- `lowly.id.complex: ${this.lowlyGeneric.id.complex.size}`,
+ `+ lowly.id.complex: ${this.lowlyGeneric.id.complex.size}`,
...Array.from(this.lowlyGeneric.id.complex.values()).map(a => ` ###${a}`),
- `lowly.class.simple: ${this.lowlyGeneric.cl.simple.size}`,
+ `+ lowly.class.simple: ${this.lowlyGeneric.cl.simple.size}`,
...Array.from(this.lowlyGeneric.cl.simple).map(a => ` ##.${a}`),
- `lowly.class.complex: ${this.lowlyGeneric.cl.complex.size}`,
+ `+ lowly.class.complex: ${this.lowlyGeneric.cl.complex.size}`,
...Array.from(this.lowlyGeneric.cl.complex.values()).map(a => ` ##.${a}`),
- `highly.simple: ${this.highlyGeneric.simple.dict.size}`,
+ `+ highly.simple: ${this.highlyGeneric.simple.dict.size}`,
...Array.from(this.highlyGeneric.simple.dict).map(a => ` ##${a}`),
- `highly.complex: ${this.lowlyGeneric.id.simple.size}`,
+ `+ highly.complex: ${this.lowlyGeneric.id.simple.size}`,
...Array.from(this.highlyGeneric.complex.dict).map(a => ` ##${a}`),
].join('\n');
};
diff --git a/src/js/devtools.js b/src/js/devtools.js
index b683270dd..892ee625b 100644
--- a/src/js/devtools.js
+++ b/src/js/devtools.js
@@ -25,12 +25,45 @@
/******************************************************************************/
+CodeMirror.registerGlobalHelper(
+ 'fold',
+ 'ubo-dump',
+ ( ) => true,
+ (cm, start) => {
+ const startLineNo = start.line;
+ const startLine = cm.getLine(startLineNo);
+ let endLineNo = startLineNo;
+ let endLine = startLine;
+ const match = /^ *(?=\+ \S)/.exec(startLine);
+ if ( match === null ) { return; }
+ const foldCandidate = ' ' + match[0];
+ const lastLineNo = cm.lastLine();
+ let nextLineNo = startLineNo + 1;
+ while ( nextLineNo < lastLineNo ) {
+ const nextLine = cm.getLine(nextLineNo);
+ if ( nextLine.startsWith(foldCandidate) === false ) {
+ if ( startLineNo >= endLineNo ) { return; }
+ return {
+ from: CodeMirror.Pos(startLineNo, startLine.length),
+ to: CodeMirror.Pos(endLineNo, endLine.length)
+ };
+ }
+ endLine = nextLine;
+ endLineNo = nextLineNo;
+ nextLineNo += 1;
+ }
+ }
+);
+
const cmEditor = new CodeMirror(
document.getElementById('console'),
{
autofocus: true,
+ foldGutter: true,
+ gutters: [ 'CodeMirror-linenumbers', 'CodeMirror-foldgutter' ],
lineNumbers: true,
lineWrapping: true,
+ mode: 'ubo-dump',
styleActiveLine: true,
undoDepth: 5,
}
diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js
index cc8a743e8..845943675 100644
--- a/src/js/static-net-filtering.js
+++ b/src/js/static-net-filtering.js
@@ -4536,21 +4536,26 @@ FilterContainer.prototype.dump = function() {
[ ThirdParty, '3rd-party' ],
]);
for ( const [ realmBits, realmName ] of realms ) {
- toOutput(0, `realm: ${realmName}`);
+ toOutput(1, `+ realm: ${realmName}`);
for ( const [ partyBits, partyName ] of partyness ) {
- toOutput(1, `party: ${partyName}`);
+ toOutput(2, `+ party: ${partyName}`);
+ const processedTypeBits = new Set();
for ( const typeName in typeNameToTypeValue ) {
- const bits = realmBits | partyBits | typeNameToTypeValue[typeName];
+ const typeBits = typeNameToTypeValue[typeName];
+ if ( processedTypeBits.has(typeBits) ) { continue; }
+ processedTypeBits.add(typeBits);
+ const bits = realmBits | partyBits | typeBits;
const ibucket = this.bitsToBucketIndices[bits];
if ( ibucket === 0 ) { continue; }
- toOutput(2, `type: ${typeName}`);
+ const thCount = this.buckets[ibucket].size;
+ toOutput(3, `+ type: ${typeName} (${thCount})`);
for ( const [ th, iunit ] of this.buckets[ibucket] ) {
thCounts.add(th);
const ths = thConstants.has(th)
? thConstants.get(th)
: `0x${th.toString(16)}`;
- toOutput(3, `th: ${ths}`);
- dumpUnit(iunit, out, 4);
+ toOutput(4, `th: ${ths}`);
+ dumpUnit(iunit, out, 5);
}
}
}
@@ -4562,22 +4567,22 @@ FilterContainer.prototype.dump = function() {
out.unshift([
'Static Network Filtering Engine internals:',
- `Distinct token hashes: ${thCounts.size.toLocaleString('en')}`,
- `Known-token sieve (Uint8Array): ${knownTokens.toLocaleString('en')} out of 65,536`,
- `Filter data (Int32Array): ${filterDataWritePtr.toLocaleString('en')}`,
- `Filter refs (JS array): ${filterRefsWritePtr.toLocaleString('en')}`,
- 'Origin trie container:',
- origHNTrieContainer.dumpInfo().split('\n').map(a => ` ${a}`).join('\n'),
- 'Request trie container:',
- destHNTrieContainer.dumpInfo().split('\n').map(a => ` ${a}`).join('\n'),
- 'Pattern trie container:',
- bidiTrie.dumpInfo().split('\n').map(a => ` ${a}`).join('\n'),
- 'Filter class stats:',
+ ` Distinct token hashes: ${thCounts.size.toLocaleString('en')}`,
+ ` Known-token sieve (Uint8Array): ${knownTokens.toLocaleString('en')} out of 65,536`,
+ ` Filter data (Int32Array): ${filterDataWritePtr.toLocaleString('en')}`,
+ ` Filter refs (JS array): ${filterRefsWritePtr.toLocaleString('en')}`,
+ ' Origin trie container:',
+ origHNTrieContainer.dumpInfo().split('\n').map(a => ` ${a}`).join('\n'),
+ ' Request trie container:',
+ destHNTrieContainer.dumpInfo().split('\n').map(a => ` ${a}`).join('\n'),
+ ' Pattern trie container:',
+ bidiTrie.dumpInfo().split('\n').map(a => ` ${a}`).join('\n'),
+ '+ Filter class stats:',
Array.from(fcCounts)
.sort((a, b) => b[1] - a[1])
- .map(a => ` ${a[0]}: ${a[1].toLocaleString('en')}`)
+ .map(a => ` ${a[0]}: ${a[1].toLocaleString('en')}`)
.join('\n'),
- 'Filter tree:',
+ '+ Filter tree:',
].join('\n'));
return out.join('\n');
};