Skip to content

Commit

Permalink
Merge pull request #286 from hawkeye116477/master
Browse files Browse the repository at this point in the history
Add all fixes for search functionality from upstream
  • Loading branch information
JustOff authored Dec 28, 2020
2 parents d618c97 + 92f7e4d commit 05d14d3
Showing 9 changed files with 496 additions and 279 deletions.
2 changes: 1 addition & 1 deletion src/1p-filters.html
Original file line number Diff line number Diff line change
@@ -39,11 +39,11 @@
<script src="lib/codemirror/lib/codemirror.js"></script>
<script src="lib/codemirror/addon/display/panel.js"></script>
<script src="lib/codemirror/addon/scroll/annotatescrollbar.js"></script>
<script src="lib/codemirror/addon/search/matchesonscrollbar.js"></script>
<script src="lib/codemirror/addon/search/searchcursor.js"></script>
<script src="lib/codemirror/addon/selection/active-line.js"></script>

<script src="js/codemirror/search.js"></script>
<script src="js/codemirror/search-thread.js"></script>
<script src="js/codemirror/ubo-static-filtering.js"></script>

<script src="js/fa-icons.js"></script>
2 changes: 1 addition & 1 deletion src/asset-viewer.html
Original file line number Diff line number Diff line change
@@ -30,11 +30,11 @@
<script src="lib/codemirror/lib/codemirror.js"></script>
<script src="lib/codemirror/addon/display/panel.js"></script>
<script src="lib/codemirror/addon/scroll/annotatescrollbar.js"></script>
<script src="lib/codemirror/addon/search/matchesonscrollbar.js"></script>
<script src="lib/codemirror/addon/search/searchcursor.js"></script>
<script src="lib/codemirror/addon/selection/active-line.js"></script>

<script src="js/codemirror/search.js"></script>
<script src="js/codemirror/search-thread.js"></script>
<script src="js/codemirror/ubo-static-filtering.js"></script>

<script src="js/fa-icons.js"></script>
41 changes: 17 additions & 24 deletions src/css/codemirror.css
Original file line number Diff line number Diff line change
@@ -36,57 +36,50 @@
direction: ltr;
display: flex;
flex-shrink: 0;
font-size: 110%;
justify-content: center;
justify-content: space-between;
padding: 0.5em;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
z-index: 1000;
}
.cm-search-widget-input {
display: inline-flex;
flex-grow: 1;
}
.cm-search-widget .fa-icon {
fill: #888;
font-size: 140%;
}
.cm-search-widget .fa-icon:not(.fa-icon-ro):hover {
fill: #000;
}
.cm-search-widget-input {
.cm-search-widget-input input {
border: 1px solid gray;
border-radius: 3px;
display: inline-flex;
max-width: 50vw;
width: 16em;
}
.cm-search-widget-input > input {
border: 0;
flex-grow: 1;
width: 100%;
max-width: 16em;
}
.cm-search-widget-input > .cm-search-widget-count {
.cm-search-widget-count {
align-items: center;
color: #888;
display: none;
display: inline-flex;
flex-grow: 0;
font-size: 80%;
padding: 0 0.4em;
pointer-events: none;
font-size: 95%;
min-width: 6em;
visibility: hidden;
}
.cm-search-widget[data-query] .cm-search-widget-count {
display: inline-flex;
.cm-search-widget[data-query] .cm-search-widget-count:not(:empty) {
visibility: visible;
}
.cm-search-widget .cm-search-widget-button:hover {
color: #000;
}
.cm-search-widget .sourceURL {
padding-left: 0.5em;
padding-right: 0.5em;
position: absolute;
left: 0;
}
.cm-search-widget .sourceURL[href=""] {
display: none;
}
.cm-searching {
border: 1px dotted black;
}

.CodeMirror-merge-l-deleted {
background-image: none;
2 changes: 1 addition & 1 deletion src/dyna-rules.html
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@
<button type="button" class="iconifiable" id="importButton"><span class="fa">&#xf019;</span><span data-i18n="rulesImport"></span></button>
<button type="button" class="iconifiable important disabled" id="editSaveButton"><span class="fa">&#xf0c7;</span><span data-i18n="rulesEditSave"></span></button>
</div>
<div id="ruleFilter"><span class="fa">&#xf0b0;</span>&ensp;<input type="text" size="20"></div>
<div id="ruleFilter"><span class="fa">&#xf0b0;</span>&ensp;<input type="search" size="20"></div>
</div>
</div>
</div>
203 changes: 203 additions & 0 deletions src/js/codemirror/search-thread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2020-present Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uBlock
*/

'use strict';

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

(( ) => {
// >>>>> start of local scope

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

// Worker context

if (
self.WorkerGlobalScope instanceof Object &&
self instanceof self.WorkerGlobalScope
) {
let content = '';

const doSearch = function(details) {
const reEOLs = /\n\r|\r\n|\n|\r/g;
const t1 = Date.now() + 750;

let reSearch;
try {
reSearch = new RegExp(details.pattern, details.flags);
} catch(ex) {
return;
}

const response = [];
const maxOffset = content.length;
let iLine = 0;
let iOffset = 0;
let size = 0;
while ( iOffset < maxOffset ) {
// Find next match
const match = reSearch.exec(content);
if ( match === null ) { break; }
// Find number of line breaks between last and current match.
reEOLs.lastIndex = 0;
const eols = content.slice(iOffset, match.index).match(reEOLs);
if ( Array.isArray(eols) ) {
iLine += eols.length;
}
// Store line
response.push(iLine);
size += 1;
// Find next line break.
reEOLs.lastIndex = reSearch.lastIndex;
const eol = reEOLs.exec(content);
iOffset = eol !== null
? reEOLs.lastIndex
: content.length;
reSearch.lastIndex = iOffset;
iLine += 1;
// Quit if this takes too long
if ( (size & 0x3FF) === 0 && Date.now() >= t1 ) { break; }
}

return response;
};

self.onmessage = function(e) {
const msg = e.data;

switch ( msg.what ) {
case 'setHaystack':
content = msg.content;
break;

case 'doSearch':
const response = doSearch(msg);
self.postMessage({ id: msg.id, response });
break;
}
};

return;
}

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

// Main context

{
const workerTTL = 5 * 60 * 1000;
const pendingResponses = new Map();

let worker;
let workerTTLTimer;
let messageId = 1;

const onWorkerMessage = function(e) {
const msg = e.data;
const resolver = pendingResponses.get(msg.id);
if ( resolver === undefined ) { return; }
pendingResponses.delete(msg.id);
resolver(msg.response);
};

const cancelPendingTasks = function() {
for ( let resolver of pendingResponses.values() ) {
resolver();
}
pendingResponses.clear();
};

const destroy = function() {
shutdown();
self.searchThread = undefined;
};

const shutdown = function() {
if ( workerTTLTimer !== undefined ) {
clearTimeout(workerTTLTimer);
workerTTLTimer = undefined;
}
if ( worker === undefined ) { return; }
worker.terminate();
worker.onmessage = undefined;
worker = undefined;
cancelPendingTasks();
};

const init = function() {
if ( self.searchThread instanceof Object === false ) { return; }
if ( worker === undefined ) {
worker = new Worker('js/codemirror/search-thread.js');
worker.onmessage = onWorkerMessage;
}
if ( workerTTLTimer !== undefined ) {
clearTimeout(workerTTLTimer);
}
workerTTLTimer = vAPI.setTimeout(shutdown, workerTTL);
};

const needHaystack = function() {
return worker instanceof Object === false;
};

const setHaystack = function(content) {
init();
worker.postMessage({ what: 'setHaystack', content });
};

const search = function(query, overwrite = true) {
init();
if ( worker instanceof Object === false ) {
return Promise.resolve();
}
if ( overwrite ) {
cancelPendingTasks();
}
const id = messageId++;
worker.postMessage({
what: 'doSearch',
id,
pattern: query.source,
flags: query.flags,
isRE: query instanceof RegExp
});
return new Promise(resolve => {
pendingResponses.set(id, resolve);
});
};

self.addEventListener(
'beforeunload',
( ) => { destroy(); },
{ once: true }
);

self.searchThread = { needHaystack, setHaystack, search, shutdown };
}

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

// <<<<< end of local scope
})();

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

void 0;
Loading

0 comments on commit 05d14d3

Please sign in to comment.