Add support for nodejs flavors

The main nodejs flavor is "npm", which is to be used to
lint/test and the publication of an official npm
package -- and by design it has dependencies on mocha,
eslint, etc.

A new flavor "dig" has been created with minimal
dependencies and which purpose is to easily allow to
write specialized code to investigate local code changes
in uBO -- and it's not meant for publication.

Consequently, "make nodejs" has been replaced with
"make npm", and a new "dig" target has been added to the
makefile, to be used for instrumenting local code changes
for investigation purpose.
This commit is contained in:
Raymond Hill 2021-08-15 10:43:36 -04:00
parent 0a11999459
commit 087da6407d
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
13 changed files with 152 additions and 226 deletions

View file

@ -39,7 +39,7 @@ jobs:
tools/make-chromium.sh ${{ steps.release_info.outputs.VERSION }} tools/make-chromium.sh ${{ steps.release_info.outputs.VERSION }}
tools/make-firefox.sh ${{ steps.release_info.outputs.VERSION }} tools/make-firefox.sh ${{ steps.release_info.outputs.VERSION }}
tools/make-thunderbird.sh ${{ steps.release_info.outputs.VERSION }} tools/make-thunderbird.sh ${{ steps.release_info.outputs.VERSION }}
tools/make-nodejs.sh ${{ steps.release_info.outputs.VERSION }} tools/make-npm.sh ${{ steps.release_info.outputs.VERSION }}
- name: Upload Chromium package - name: Upload Chromium package
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
@ -73,6 +73,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: dist/build/uBlock0_${{ steps.release_info.outputs.VERSION }}.nodejs.tgz asset_path: dist/build/uBlock0_${{ steps.release_info.outputs.VERSION }}.npm.tgz
asset_name: uBlock0_${{ steps.release_info.outputs.VERSION }}.nodejs.tgz asset_name: uBlock0_${{ steps.release_info.outputs.VERSION }}.npm.tgz
asset_content_type: application/octet-stream asset_content_type: application/octet-stream

View file

@ -1,4 +1,4 @@
.PHONY: all clean test lint chromium firefox nodejs .PHONY: all clean test lint chromium firefox npm
sources := $(wildcard src/* src/*/* src/*/*/* src/*/*/*/*) sources := $(wildcard src/* src/*/* src/*/*/* src/*/*/*/*)
platform := $(wildcard platform/* platform/*/*) platform := $(wildcard platform/* platform/*/*)
@ -7,7 +7,7 @@ assets := $(wildcard submodules/uAssets/* \
submodules/uAssets/*/*/* \ submodules/uAssets/*/*/* \
submodules/uAssets/*/*/*/*) submodules/uAssets/*/*/*/*)
all: chromium firefox nodejs all: chromium firefox npm
dist/build/uBlock0.chromium: tools/make-chromium.sh $(sources) $(platform) $(assets) dist/build/uBlock0.chromium: tools/make-chromium.sh $(sources) $(platform) $(assets)
tools/make-chromium.sh tools/make-chromium.sh
@ -21,17 +21,23 @@ dist/build/uBlock0.firefox: tools/make-firefox.sh $(sources) $(platform) $(asset
# Build the extension for Firefox. # Build the extension for Firefox.
firefox: dist/build/uBlock0.firefox firefox: dist/build/uBlock0.firefox
dist/build/uBlock0.nodejs: tools/make-nodejs.sh $(sources) $(platform) $(assets) dist/build/uBlock0.npm: tools/make-nodejs.sh $(sources) $(platform) $(assets)
tools/make-nodejs.sh tools/make-npm.sh
# Build the Node.js package. # Build the Node.js package.
nodejs: dist/build/uBlock0.nodejs npm: dist/build/uBlock0.npm
lint: nodejs lint: npm
cd dist/build/uBlock0.nodejs && npm install && npm run lint cd dist/build/uBlock0.npm && npm install && npm run lint
test: nodejs test: npm
cd dist/build/uBlock0.nodejs && npm install && npm run test cd dist/build/uBlock0.npm && npm install && npm run test
dist/build/uBlock0.dig: tools/make-nodejs.sh $(sources) $(platform) $(assets)
tools/make-dig.sh
dig: dist/build/uBlock0.dig
cd dist/build/uBlock0.dig && npm install && npm run test
# Update submodules. # Update submodules.
update-submodules: update-submodules:

View file

@ -102,7 +102,7 @@ and use this capability now if you figure out the details.
You can directly use specific APIs exposed by this package, here are some of You can directly use specific APIs exposed by this package, here are some of
them, which are used internally by uBO's SNFE. them, which are used internally by uBO's SNFE.
### `HNTrieContainer` ### HNTrieContainer
A well optimised [compressed trie](https://en.wikipedia.org/wiki/Trie#Compressing_tries) A well optimised [compressed trie](https://en.wikipedia.org/wiki/Trie#Compressing_tries)
container specialized to specifically store and lookup hostnames. container specialized to specifically store and lookup hostnames.

View file

@ -95,8 +95,7 @@ function pslInit(raw) {
return globals.publicSuffixList; return globals.publicSuffixList;
} }
const require = createRequire(import.meta.url); // jshint ignore:line raw = readFileSync(resolve(__dirname, './assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat'), 'utf8')
raw = require('./data/effective_tld_names.json');
if ( typeof raw !== 'string' || raw.trim() === '' ) { if ( typeof raw !== 'string' || raw.trim() === '' ) {
console.error('Unable to populate public suffix list'); console.error('Unable to populate public suffix list');
return; return;
@ -203,14 +202,14 @@ class MockStorage {
} }
const fctx = new FilteringContext(); const fctx = new FilteringContext();
let snfeInstance = null; let snfeProxyInstance = null;
class StaticNetFilteringEngine { class StaticNetFilteringEngine {
constructor() { constructor() {
if ( snfeInstance !== null ) { if ( snfeProxyInstance !== null ) {
throw new Error('Only a single instance is supported.'); throw new Error('Only a single instance is supported.');
} }
snfeInstance = this; snfeProxyInstance = this;
} }
async useLists(lists) { async useLists(lists) {
@ -253,6 +252,11 @@ class StaticNetFilteringEngine {
return instance; return instance;
} }
static release() {
useLists([]);
snfeProxyInstance = null;
}
} }
/******************************************************************************/ /******************************************************************************/

View file

@ -1,160 +0,0 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-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
*/
/* eslint-disable-next-line no-redeclare */
/* globals process */
'use strict';
/******************************************************************************/
import { strict as assert } from 'assert';
import { spawn } from "child_process";
import { createRequire } from 'module';
import { promisify } from 'util';
import {
enableWASM,
StaticNetFilteringEngine,
} from './index.js';
import HNTrieContainer from './js/hntrie.js';
/******************************************************************************/
function fetch(listName) {
return new Promise(resolve => {
const require = createRequire(import.meta.url); // jshint ignore:line
resolve(require(`./data/${listName}.json`));
});
}
function testSNFE(engine) {
let result = 0;
// Tests
// Not blocked
result = engine.matchRequest({
originURL: 'https://www.bloomberg.com/',
url: 'https://www.bloomberg.com/tophat/assets/v2.6.1/that.css',
type: 'stylesheet'
});
if ( result !== 0 ) {
console.log(engine.toLogData());
}
// Blocked
result = engine.matchRequest({
originURL: 'https://www.bloomberg.com/',
url: 'https://securepubads.g.doubleclick.net/tag/js/gpt.js',
type: 'script'
});
if ( result !== 0 ) {
console.log(engine.toLogData());
}
// Unblocked
result = engine.matchRequest({
originURL: 'https://www.bloomberg.com/',
url: 'https://sourcepointcmp.bloomberg.com/ccpa.js',
type: 'script'
});
if ( result !== 0 ) {
console.log(engine.toLogData());
}
}
async function doSNFE() {
const engine = await StaticNetFilteringEngine.create();
await engine.useLists([
fetch('easylist').then(raw => ({ name: 'easylist', raw })),
fetch('easyprivacy').then(raw => ({ name: 'easyprivacy', raw })),
]);
testSNFE(engine);
const serialized = await engine.serialize();
engine.useLists([]);
assert.notDeepEqual(await engine.serialize(), serialized);
testSNFE(engine);
await engine.deserialize(serialized);
assert.deepEqual(await engine.serialize(), serialized);
testSNFE(engine);
}
async function doHNTrie() {
const trieContainer = new HNTrieContainer();
const aTrie = trieContainer.createOne();
aTrie.add('example.org');
aTrie.add('example.com');
const anotherTrie = trieContainer.createOne();
anotherTrie.add('foo.invalid');
anotherTrie.add('bar.invalid');
// matches() return the position at which the match starts, or -1 when
// there is no match.
// Matches: return 4
console.log("aTrie.matches('www.example.org')", aTrie.matches('www.example.org'));
// Does not match: return -1
console.log("aTrie.matches('www.foo.invalid')", aTrie.matches('www.foo.invalid'));
// Does not match: return -1
console.log("anotherTrie.matches('www.example.org')", anotherTrie.matches('www.example.org'));
// Matches: return 0
console.log("anotherTrie.matches('foo.invalid')", anotherTrie.matches('foo.invalid'));
}
async function spawnMocha() {
await promisify(spawn)('mocha', [ '--experimental-vm-modules', '--no-warnings', 'tests' ], { stdio: [ 'inherit', 'inherit', 'inherit' ] });
}
async function main() {
try {
const result = await enableWASM();
if ( result !== true ) {
console.log('Failed to enable all WASM code paths');
}
} catch(ex) {
console.log(ex);
}
await doSNFE();
await doHNTrie();
if ( process.argv[2] === '--mocha' ) {
await spawnMocha();
}
}
main();
/******************************************************************************/

46
platform/npm/test.js Normal file
View file

@ -0,0 +1,46 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-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
*/
/* eslint-disable-next-line no-redeclare */
/* globals process */
'use strict';
/******************************************************************************/
import { spawn } from "child_process";
import { promisify } from 'util';
/******************************************************************************/
async function spawnMocha() {
await promisify(spawn)('mocha', [ '--experimental-vm-modules', '--no-warnings', 'tests' ], { stdio: [ 'inherit', 'inherit', 'inherit' ] });
}
async function main() {
if ( process.argv[2] === '--mocha' ) {
await spawnMocha();
}
}
main();
/******************************************************************************/

17
tools/make-dig.sh Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env bash
#
# This script assumes a linux environment
set -e
DES="dist/build/uBlock0.dig"
./tools/make-nodejs.sh $DES
./tools/make-assets.sh $DES
cp -R platform/dig/* $DES/
cd $DES
npm run build
echo "*** uBlock0.dig: Package done."

View file

@ -4,18 +4,7 @@
set -e set -e
DES=dist/build/uBlock0.nodejs DES=$1
TMPDIR=tmp
mkdir -p $TMPDIR
# Save existing npm dependencies if present so that we do not have to fetch
# them all again
if [ -d "$DES/node_modules" ]; then
mv "$DES/node_modules" "$TMPDIR/node_modules"
fi
rm -rf $DES
mkdir -p $DES/js mkdir -p $DES/js
cp src/js/base64-custom.js $DES/js cp src/js/base64-custom.js $DES/js
@ -47,42 +36,6 @@ node -pe "JSON.stringify(Array.from(fs.readFileSync('src/js/wasm/biditrie.wasm')
node -pe "JSON.stringify(Array.from(fs.readFileSync('src/lib/publicsuffixlist/wasm/publicsuffixlist.wasm')))" \ node -pe "JSON.stringify(Array.from(fs.readFileSync('src/lib/publicsuffixlist/wasm/publicsuffixlist.wasm')))" \
> $DES/lib/publicsuffixlist/wasm/publicsuffixlist.wasm.json > $DES/lib/publicsuffixlist/wasm/publicsuffixlist.wasm.json
git submodule update --depth 1 --init
UASSETS=submodules/uAssets
# https://github.com/uBlockOrigin/uBlock-issues/issues/1664#issuecomment-888332409
THIRDPARTY=$UASSETS/thirdparties/publicsuffix.org
mkdir -p $DES/data
node -pe "JSON.stringify(fs.readFileSync('$THIRDPARTY/list/effective_tld_names.dat', 'utf8'))" \
> $DES/data/effective_tld_names.json
THIRDPARTY=$UASSETS/thirdparties/easylist-downloads.adblockplus.org
node -pe "JSON.stringify(fs.readFileSync('$THIRDPARTY/easylist.txt', 'utf8'))" \
> $DES/data/easylist.json
node -pe "JSON.stringify(fs.readFileSync('$THIRDPARTY/easyprivacy.txt', 'utf8'))" \
> $DES/data/easyprivacy.json
cp platform/nodejs/.*.json $DES/
cp platform/nodejs/*.js $DES/ cp platform/nodejs/*.js $DES/
cp platform/nodejs/*.json $DES/
cp platform/nodejs/README.md $DES/ cp platform/nodejs/README.md $DES/
cp LICENSE.txt $DES/ cp LICENSE.txt $DES/
cp -R platform/nodejs/tests $DES/
cd $DES
npm run build
tarballname=$(npm pack 2> /dev/null)
if [ "$1" ]; then
echo "*** uBlock0.nodejs: Creating versioned package..."
mv $tarballname ../uBlock0_"$1".nodejs.tgz
else
echo "*** uBlock0.nodejs: Creating plain package..."
mv $tarballname ../uBlock0.nodejs.tgz
fi
cd -
# Restore saved npm dependencies
if [ -d "$TMPDIR/node_modules" ]; then
mv "$TMPDIR/node_modules" "$DES/node_modules"
fi
echo "*** uBlock0.nodejs: Package done."

60
tools/make-npm.sh Executable file
View file

@ -0,0 +1,60 @@
#!/usr/bin/env bash
#
# This script assumes a linux environment
set -e
DES="dist/build/uBlock0.npm"
TMPDIR=tmp
mkdir -p $TMPDIR
# Save existing npm dependencies if present so that we do not have to fetch
# them all again
if [ -d "$DES/node_modules" ]; then
mv "$DES/node_modules" "$TMPDIR/node_modules"
fi
rm -rf $DES
./tools/make-nodejs.sh $DES
UASSETS=submodules/uAssets
# https://github.com/uBlockOrigin/uBlock-issues/issues/1664#issuecomment-888332409
mkdir -p $DES/assets/thirdparties/publicsuffix.org/list
THIRDPARTY=$UASSETS/thirdparties/publicsuffix.org
node -pe "JSON.stringify(fs.readFileSync('$THIRDPARTY/list/effective_tld_names.dat', 'utf8'))" \
> $DES/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat
mkdir -p $DES/data
THIRDPARTY=$UASSETS/thirdparties/easylist-downloads.adblockplus.org
node -pe "JSON.stringify(fs.readFileSync('$THIRDPARTY/easylist.txt', 'utf8'))" \
> $DES/data/easylist.json
node -pe "JSON.stringify(fs.readFileSync('$THIRDPARTY/easyprivacy.txt', 'utf8'))" \
> $DES/data/easyprivacy.json
# Target-specific
cp platform/npm/*.json $DES/
cp platform/npm/.*.json $DES/
cp platform/npm/*.js $DES/
cp -R platform/npm/tests $DES/
cd $DES
npm run build
tarballname=$(npm pack 2> /dev/null)
if [ "$1" ]; then
echo "*** uBlock0.npm: Creating versioned package..."
mv $tarballname ../uBlock0_$1.npm.tgz
else
echo "*** uBlock0.npm: Creating plain package..."
mv $tarballname ../uBlock0.npm.tgz
fi
cd -
# Restore saved npm dependencies
if [ -d "$TMPDIR/node_modules" ]; then
mv "$TMPDIR/node_modules" "$DES/node_modules"
fi
echo "*** uBlock0.npm: Package done."