tests: added test-browser static files
This commit is contained in:
parent
25ab579634
commit
96d5e7b206
107
misc/test-browser/assert.js
Normal file
107
misc/test-browser/assert.js
Normal file
@ -0,0 +1,107 @@
|
||||
|
||||
function throwError(message, info) {
|
||||
const error = new Error(`AssertionError: ${ message }`);
|
||||
error.code = "ERR_ASSERTION";
|
||||
for (const key of info) { error[key] = info[key]; }
|
||||
throw error;
|
||||
}
|
||||
|
||||
export function equal(actual, expected, reason) {
|
||||
if (actual != expected) {
|
||||
if (reason == null) { reason = `${ actual } == ${ expected }`; }
|
||||
|
||||
throwError(reason, { actual, expected, operator: "==" });
|
||||
}
|
||||
}
|
||||
|
||||
function isDeepEqual(actual, expected, memo) {
|
||||
if (actual === expected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// One or both things aren't objects
|
||||
if (actual === null || typeof(expected) !== 'object') {
|
||||
if (expected === null || typeof(expected) !== 'object') {
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
} else if (expected === null || typeof(expected) !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.isArray(actual)) {
|
||||
if (!Array.isArray(expected) || actual.length !== expected.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
if (!isDeepEqual(actual[i], expected[i])) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object
|
||||
const keysActual = Object.keys(actual).sort(), keysExpected = Object.keys(expected).sort();
|
||||
if (!isDeepEqual(keysActual, keysExpected)) { return false; }
|
||||
for (const key of keysActual) {
|
||||
if (!isDeepEqual(actual[key], expected[key], memo)) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function deepEqual(actual, expected, reason) {
|
||||
const memo = [ ];
|
||||
const isOk = isDeepEqual(actual, expected, memo);
|
||||
if (!isOk) {
|
||||
equal(actual, expected, reason);
|
||||
}
|
||||
}
|
||||
|
||||
export function ok(check, reason) {
|
||||
equal(!!check, true, reason);
|
||||
}
|
||||
|
||||
export function throws(func, checkFunc, reason) {
|
||||
try {
|
||||
func();
|
||||
|
||||
} catch (e) {
|
||||
if (checkFunc(e)) { return true; }
|
||||
|
||||
throwError(`The expected exception validation function returned false`, {
|
||||
actual: e,
|
||||
expected: checkFunc,
|
||||
operation: "throws"
|
||||
});
|
||||
}
|
||||
|
||||
throwError("Missing expected exception", {
|
||||
operator: "throws"
|
||||
});
|
||||
}
|
||||
|
||||
export async function rejects(func, checkFunc, reason) {
|
||||
try {
|
||||
await func();
|
||||
} catch (e) {
|
||||
if (checkFunc(e)) { return true; }
|
||||
|
||||
throwError(`The rejection validation function returned false`, {
|
||||
actual: e,
|
||||
expected: checkFunc,
|
||||
operation: "throws"
|
||||
});
|
||||
}
|
||||
|
||||
throwError("Missing rejection", {
|
||||
operator: "rejects"
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
equal, deepEqual, ok, rejects, throws
|
||||
};
|
26
misc/test-browser/index.html
Normal file
26
misc/test-browser/index.html
Normal file
@ -0,0 +1,26 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello World!!</h1>
|
||||
<div>Please check the console for test output...</div>
|
||||
|
||||
<div id="mocha"></div>
|
||||
|
||||
<script type="module">
|
||||
// Must import Mocha first; completely
|
||||
await import("./static/mocha.js");
|
||||
|
||||
// Load our custom Reporter (after importing mocha)
|
||||
import { MyReporter } from "/static/reporter.js";
|
||||
|
||||
// Setup the global environment and set out reporter
|
||||
mocha.setup({ ui: 'bdd' });
|
||||
mocha.reporter(MyReporter);
|
||||
|
||||
// Import the tests
|
||||
await import("./tests/index.js");
|
||||
|
||||
// Run Mocha!
|
||||
mocha.run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
20617
misc/test-browser/mocha.js
Normal file
20617
misc/test-browser/mocha.js
Normal file
File diff suppressed because one or more lines are too long
1
misc/test-browser/mocha.js.map
Normal file
1
misc/test-browser/mocha.js.map
Normal file
File diff suppressed because one or more lines are too long
218
misc/test-browser/reporter.js
Normal file
218
misc/test-browser/reporter.js
Normal file
@ -0,0 +1,218 @@
|
||||
'use strict';
|
||||
|
||||
/* c8 ignore start */
|
||||
|
||||
await import("/static/mocha.js");
|
||||
|
||||
const {
|
||||
EVENT_RUN_BEGIN,
|
||||
EVENT_RUN_END,
|
||||
EVENT_TEST_BEGIN,
|
||||
EVENT_TEST_END,
|
||||
EVENT_TEST_FAIL,
|
||||
EVENT_TEST_PASS,
|
||||
EVENT_SUITE_BEGIN,
|
||||
EVENT_SUITE_END
|
||||
} = Mocha.Runner.constants;
|
||||
|
||||
|
||||
// See: https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
|
||||
let disableColor = true;
|
||||
|
||||
const Colors = {
|
||||
"blue": "\x1b[0;34m",
|
||||
"blue+": "\x1b[0;1;34m",
|
||||
"cyan": "\x1b[0;36m",
|
||||
"cyan+": "\x1b[0;1;36m",
|
||||
"green": "\x1b[0;32m",
|
||||
"green+": "\x1b[0;1;32m",
|
||||
"magenta-": "\x1b[0;2;35m",
|
||||
"magenta": "\x1b[0;35m",
|
||||
"magenta+": "\x1b[0;1;35m",
|
||||
"red": "\x1b[0;31m",
|
||||
"red+": "\x1b[0;1;31m",
|
||||
"yellow": "\x1b[0;33m",
|
||||
"yellow+": "\x1b[0;1;33m",
|
||||
"dim": "\x1b[0;2;37m",
|
||||
"bold": "\x1b[0;1;37m",
|
||||
"normal": "\x1b[0m"
|
||||
};
|
||||
|
||||
function colorify(text) {
|
||||
return unescapeColor(text.replace(/(<([a-z+]+)>)/g, (all, _, color) => {
|
||||
if (disableColor) { return ""; }
|
||||
|
||||
const seq = Colors[color];
|
||||
if (seq == null) {
|
||||
console.log("UNKNOWN COLOR:", color);
|
||||
return "";
|
||||
}
|
||||
return seq;
|
||||
})) + (disableColor ? "": Colors.normal);
|
||||
}
|
||||
|
||||
function escapeColor(text) {
|
||||
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
}
|
||||
|
||||
function unescapeColor(text) {
|
||||
return text.replace(/>/g, ">").replace(/</g, "<").replace(/&/g, "&");
|
||||
}
|
||||
|
||||
function getString(value) {
|
||||
if (value instanceof Error) {
|
||||
return value.stack;
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
|
||||
// To prevent environments from thinking we're dead due to lack of
|
||||
// output, we force output after 20s
|
||||
function getTime() { return (new Date()).getTime(); }
|
||||
const KEEP_ALIVE = 20 * 1000;
|
||||
|
||||
// this reporter outputs test results, indenting two spaces per suite
|
||||
export class MyReporter {
|
||||
constructor(runner) {
|
||||
this._errors = [ ];
|
||||
this._indents = 1;
|
||||
this._lastLog = getTime();
|
||||
this._lastPass = "";
|
||||
this._lastPrefix = null;
|
||||
this._lastPrefixHeader = null;
|
||||
this._testLogs = [ ];
|
||||
this._suiteLogs = [ ];
|
||||
this._prefixCount = 0;
|
||||
const stats = runner.stats;
|
||||
|
||||
runner.once(EVENT_RUN_BEGIN, () => {
|
||||
|
||||
}).on(EVENT_SUITE_BEGIN, (suite) => {
|
||||
this._suiteLogs.push([ ]);
|
||||
suite._ethersLog = (text) => {
|
||||
this._suiteLogs[this._suiteLogs.length - 1].push(getString(text))
|
||||
};
|
||||
if (suite.title.trim()) {
|
||||
this.log(`<blue+>Suite: ${ escapeColor(suite.title) }`)
|
||||
}
|
||||
this.increaseIndent();
|
||||
|
||||
}).on(EVENT_SUITE_END, (suite) => {
|
||||
this.flush(true);
|
||||
this.decreaseIndent();
|
||||
const logs = this._suiteLogs.pop();
|
||||
if (logs.length) {
|
||||
logs.join("\n").split("\n").forEach((line) => {
|
||||
this.log(` <magenta+>>> <dim>${ escapeColor(line) }`);
|
||||
});
|
||||
}
|
||||
if (suite.title.trim()) { this.log(""); }
|
||||
|
||||
}).on(EVENT_TEST_BEGIN, (test) => {
|
||||
this._testLogs.push([ ]);
|
||||
test._ethersLog = (text) => {
|
||||
this._testLogs[this._testLogs.length - 1].push(getString(text))
|
||||
};
|
||||
|
||||
}).on(EVENT_TEST_END, (test) => {
|
||||
const logs = this._testLogs.pop();
|
||||
if (logs.length) {
|
||||
this.flush(false);
|
||||
logs.join("\n").split("\n").forEach((line) => {
|
||||
this.log(` <cyan+>>> <cyan->${ escapeColor(line) }`);
|
||||
});
|
||||
}
|
||||
|
||||
}).on(EVENT_TEST_PASS, (test) => {
|
||||
this.addPass(test.title);
|
||||
|
||||
}).on(EVENT_TEST_FAIL, (test, error) => {
|
||||
this.flush();
|
||||
this._errors.push({ test, error });
|
||||
this.log(
|
||||
` [ <red+>fail(${ this._errors.length }): <red>${ escapeColor(test.title) } - <normal>${ escapeColor(error.message) } ]`
|
||||
);
|
||||
|
||||
}).once(EVENT_RUN_END, () => {
|
||||
this.flush(true);
|
||||
this.indent = 0;
|
||||
|
||||
if (this._errors.length) {
|
||||
this._errors.forEach(({ test, error }, index) => {
|
||||
this.log("<cyan+>---------------------");
|
||||
this.log(`<red+>ERROR ${ index + 1 }: <red>${ escapeColor(test.title) }`);
|
||||
this.log(escapeColor(error.toString()));
|
||||
});
|
||||
this.log("<cyan+>=====================");
|
||||
}
|
||||
|
||||
const { duration, passes, failures } = stats;
|
||||
const total = passes + failures;
|
||||
this.log(`<bold>Done: <green+>${ passes }<green>/${ total } passed <red>(<red+>${ failures } <red>failed)`);
|
||||
|
||||
const status = (failures > 0) ? 1: 0;
|
||||
this.log(`#status=${ status }`);
|
||||
});
|
||||
}
|
||||
|
||||
log(line) {
|
||||
this._lastLog = getTime();
|
||||
const indent = Array(this._indents).join(' ');
|
||||
console.log(`${ indent }${ colorify(line) }`);
|
||||
}
|
||||
|
||||
addPass(line) {
|
||||
const prefix = line.split(":")[0];
|
||||
if (prefix === this._lastPrefix) {
|
||||
this._prefixCount++;
|
||||
if (getTime() - this._lastLog > KEEP_ALIVE) {
|
||||
const didLog = this.flush(false);
|
||||
// Nothing was output, so show *something* so the
|
||||
// environment knows we're still alive and kicking
|
||||
if (!didLog) {
|
||||
this.log(" <yellow>[ keep-alive; forced output ]")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.flush(true);
|
||||
this._lastPrefixHeader = null;
|
||||
this._lastPrefix = prefix;
|
||||
this._prefixCount = 1;
|
||||
}
|
||||
this._lastLine = line;
|
||||
}
|
||||
|
||||
flush(reset) {
|
||||
let didLog = false;
|
||||
if (this._lastPrefix != null) {
|
||||
if (this._prefixCount === 1 && this._lastPrefixHeader == null) {
|
||||
this.log(escapeColor(this._lastLine));
|
||||
didLog = true;
|
||||
} else if (this._prefixCount > 0) {
|
||||
if (this._lastPrefixHeader !== this._lastPrefix) {
|
||||
this.log(`<cyan>${ escapeColor(this._lastPrefix) }:`);
|
||||
this._lastPrefixHeader = this._lastPrefix;
|
||||
}
|
||||
this.log(` - ${ this._prefixCount } tests passed (prefix coalesced)`);
|
||||
didLog = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
this._lastPrefixHeader = null;
|
||||
this._lastPrefix = null;
|
||||
}
|
||||
|
||||
this._prefixCount = 0;
|
||||
|
||||
return didLog;
|
||||
}
|
||||
|
||||
increaseIndent() { this._indents++; }
|
||||
|
||||
decreaseIndent() { this._indents--; }
|
||||
}
|
||||
|
||||
//module.exports = MyReporter;
|
||||
|
||||
/* c8 ignore stop */
|
376
misc/test-browser/tiny-inflate.js
Normal file
376
misc/test-browser/tiny-inflate.js
Normal file
@ -0,0 +1,376 @@
|
||||
var TINF_OK = 0;
|
||||
var TINF_DATA_ERROR = -3;
|
||||
|
||||
function Tree() {
|
||||
this.table = new Uint16Array(16); /* table of code length counts */
|
||||
this.trans = new Uint16Array(288); /* code -> symbol translation table */
|
||||
}
|
||||
|
||||
function Data(source, dest) {
|
||||
this.source = source;
|
||||
this.sourceIndex = 0;
|
||||
this.tag = 0;
|
||||
this.bitcount = 0;
|
||||
|
||||
this.dest = dest;
|
||||
this.destLen = 0;
|
||||
|
||||
this.ltree = new Tree(); /* dynamic length/symbol tree */
|
||||
this.dtree = new Tree(); /* dynamic distance tree */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------- *
|
||||
* -- uninitialized global data (static structures) -- *
|
||||
* --------------------------------------------------- */
|
||||
|
||||
var sltree = new Tree();
|
||||
var sdtree = new Tree();
|
||||
|
||||
/* extra bits and base tables for length codes */
|
||||
var length_bits = new Uint8Array(30);
|
||||
var length_base = new Uint16Array(30);
|
||||
|
||||
/* extra bits and base tables for distance codes */
|
||||
var dist_bits = new Uint8Array(30);
|
||||
var dist_base = new Uint16Array(30);
|
||||
|
||||
/* special ordering of code length codes */
|
||||
var clcidx = new Uint8Array([
|
||||
16, 17, 18, 0, 8, 7, 9, 6,
|
||||
10, 5, 11, 4, 12, 3, 13, 2,
|
||||
14, 1, 15
|
||||
]);
|
||||
|
||||
/* used by tinf_decode_trees, avoids allocations every call */
|
||||
var code_tree = new Tree();
|
||||
var lengths = new Uint8Array(288 + 32);
|
||||
|
||||
/* ----------------------- *
|
||||
* -- utility functions -- *
|
||||
* ----------------------- */
|
||||
|
||||
/* build extra bits and base tables */
|
||||
function tinf_build_bits_base(bits, base, delta, first) {
|
||||
var i, sum;
|
||||
|
||||
/* build bits table */
|
||||
for (i = 0; i < delta; ++i) bits[i] = 0;
|
||||
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta | 0;
|
||||
|
||||
/* build base table */
|
||||
for (sum = first, i = 0; i < 30; ++i) {
|
||||
base[i] = sum;
|
||||
sum += 1 << bits[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* build the fixed huffman trees */
|
||||
function tinf_build_fixed_trees(lt, dt) {
|
||||
var i;
|
||||
|
||||
/* build fixed length tree */
|
||||
for (i = 0; i < 7; ++i) lt.table[i] = 0;
|
||||
|
||||
lt.table[7] = 24;
|
||||
lt.table[8] = 152;
|
||||
lt.table[9] = 112;
|
||||
|
||||
for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i;
|
||||
for (i = 0; i < 144; ++i) lt.trans[24 + i] = i;
|
||||
for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i;
|
||||
for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i;
|
||||
|
||||
/* build fixed distance tree */
|
||||
for (i = 0; i < 5; ++i) dt.table[i] = 0;
|
||||
|
||||
dt.table[5] = 32;
|
||||
|
||||
for (i = 0; i < 32; ++i) dt.trans[i] = i;
|
||||
}
|
||||
|
||||
/* given an array of code lengths, build a tree */
|
||||
var offs = new Uint16Array(16);
|
||||
|
||||
function tinf_build_tree(t, lengths, off, num) {
|
||||
var i, sum;
|
||||
|
||||
/* clear code length count table */
|
||||
for (i = 0; i < 16; ++i) t.table[i] = 0;
|
||||
|
||||
/* scan symbol lengths, and sum code length counts */
|
||||
for (i = 0; i < num; ++i) t.table[lengths[off + i]]++;
|
||||
|
||||
t.table[0] = 0;
|
||||
|
||||
/* compute offset table for distribution sort */
|
||||
for (sum = 0, i = 0; i < 16; ++i) {
|
||||
offs[i] = sum;
|
||||
sum += t.table[i];
|
||||
}
|
||||
|
||||
/* create code->symbol translation table (symbols sorted by code) */
|
||||
for (i = 0; i < num; ++i) {
|
||||
if (lengths[off + i]) t.trans[offs[lengths[off + i]]++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------- *
|
||||
* -- decode functions -- *
|
||||
* ---------------------- */
|
||||
|
||||
/* get one bit from source stream */
|
||||
function tinf_getbit(d) {
|
||||
/* check if tag is empty */
|
||||
if (!d.bitcount--) {
|
||||
/* load next tag */
|
||||
d.tag = d.source[d.sourceIndex++];
|
||||
d.bitcount = 7;
|
||||
}
|
||||
|
||||
/* shift bit out of tag */
|
||||
var bit = d.tag & 1;
|
||||
d.tag >>>= 1;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
/* read a num bit value from a stream and add base */
|
||||
function tinf_read_bits(d, num, base) {
|
||||
if (!num)
|
||||
return base;
|
||||
|
||||
while (d.bitcount < 24) {
|
||||
d.tag |= d.source[d.sourceIndex++] << d.bitcount;
|
||||
d.bitcount += 8;
|
||||
}
|
||||
|
||||
var val = d.tag & (0xffff >>> (16 - num));
|
||||
d.tag >>>= num;
|
||||
d.bitcount -= num;
|
||||
return val + base;
|
||||
}
|
||||
|
||||
/* given a data stream and a tree, decode a symbol */
|
||||
function tinf_decode_symbol(d, t) {
|
||||
while (d.bitcount < 24) {
|
||||
d.tag |= d.source[d.sourceIndex++] << d.bitcount;
|
||||
d.bitcount += 8;
|
||||
}
|
||||
|
||||
var sum = 0, cur = 0, len = 0;
|
||||
var tag = d.tag;
|
||||
|
||||
/* get more bits while code value is above sum */
|
||||
do {
|
||||
cur = 2 * cur + (tag & 1);
|
||||
tag >>>= 1;
|
||||
++len;
|
||||
|
||||
sum += t.table[len];
|
||||
cur -= t.table[len];
|
||||
} while (cur >= 0);
|
||||
|
||||
d.tag = tag;
|
||||
d.bitcount -= len;
|
||||
|
||||
return t.trans[sum + cur];
|
||||
}
|
||||
|
||||
/* given a data stream, decode dynamic trees from it */
|
||||
function tinf_decode_trees(d, lt, dt) {
|
||||
var hlit, hdist, hclen;
|
||||
var i, num, length;
|
||||
|
||||
/* get 5 bits HLIT (257-286) */
|
||||
hlit = tinf_read_bits(d, 5, 257);
|
||||
|
||||
/* get 5 bits HDIST (1-32) */
|
||||
hdist = tinf_read_bits(d, 5, 1);
|
||||
|
||||
/* get 4 bits HCLEN (4-19) */
|
||||
hclen = tinf_read_bits(d, 4, 4);
|
||||
|
||||
for (i = 0; i < 19; ++i) lengths[i] = 0;
|
||||
|
||||
/* read code lengths for code length alphabet */
|
||||
for (i = 0; i < hclen; ++i) {
|
||||
/* get 3 bits code length (0-7) */
|
||||
var clen = tinf_read_bits(d, 3, 0);
|
||||
lengths[clcidx[i]] = clen;
|
||||
}
|
||||
|
||||
/* build code length tree */
|
||||
tinf_build_tree(code_tree, lengths, 0, 19);
|
||||
|
||||
/* decode code lengths for the dynamic trees */
|
||||
for (num = 0; num < hlit + hdist;) {
|
||||
var sym = tinf_decode_symbol(d, code_tree);
|
||||
|
||||
switch (sym) {
|
||||
case 16:
|
||||
/* copy previous code length 3-6 times (read 2 bits) */
|
||||
var prev = lengths[num - 1];
|
||||
for (length = tinf_read_bits(d, 2, 3); length; --length) {
|
||||
lengths[num++] = prev;
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
/* repeat code length 0 for 3-10 times (read 3 bits) */
|
||||
for (length = tinf_read_bits(d, 3, 3); length; --length) {
|
||||
lengths[num++] = 0;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
/* repeat code length 0 for 11-138 times (read 7 bits) */
|
||||
for (length = tinf_read_bits(d, 7, 11); length; --length) {
|
||||
lengths[num++] = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* values 0-15 represent the actual code lengths */
|
||||
lengths[num++] = sym;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* build dynamic trees */
|
||||
tinf_build_tree(lt, lengths, 0, hlit);
|
||||
tinf_build_tree(dt, lengths, hlit, hdist);
|
||||
}
|
||||
|
||||
/* ----------------------------- *
|
||||
* -- block inflate functions -- *
|
||||
* ----------------------------- */
|
||||
|
||||
/* given a stream and two trees, inflate a block of data */
|
||||
function tinf_inflate_block_data(d, lt, dt) {
|
||||
while (1) {
|
||||
var sym = tinf_decode_symbol(d, lt);
|
||||
|
||||
/* check for end of block */
|
||||
if (sym === 256) {
|
||||
return TINF_OK;
|
||||
}
|
||||
|
||||
if (sym < 256) {
|
||||
d.dest[d.destLen++] = sym;
|
||||
} else {
|
||||
var length, dist, offs;
|
||||
var i;
|
||||
|
||||
sym -= 257;
|
||||
|
||||
/* possibly get more bits from length code */
|
||||
length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
|
||||
|
||||
dist = tinf_decode_symbol(d, dt);
|
||||
|
||||
/* possibly get more bits from distance code */
|
||||
offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
|
||||
|
||||
/* copy match */
|
||||
for (i = offs; i < offs + length; ++i) {
|
||||
d.dest[d.destLen++] = d.dest[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* inflate an uncompressed block of data */
|
||||
function tinf_inflate_uncompressed_block(d) {
|
||||
var length, invlength;
|
||||
var i;
|
||||
|
||||
/* unread from bitbuffer */
|
||||
while (d.bitcount > 8) {
|
||||
d.sourceIndex--;
|
||||
d.bitcount -= 8;
|
||||
}
|
||||
|
||||
/* get length */
|
||||
length = d.source[d.sourceIndex + 1];
|
||||
length = 256 * length + d.source[d.sourceIndex];
|
||||
|
||||
/* get one's complement of length */
|
||||
invlength = d.source[d.sourceIndex + 3];
|
||||
invlength = 256 * invlength + d.source[d.sourceIndex + 2];
|
||||
|
||||
/* check length */
|
||||
if (length !== (~invlength & 0x0000ffff))
|
||||
return TINF_DATA_ERROR;
|
||||
|
||||
d.sourceIndex += 4;
|
||||
|
||||
/* copy block */
|
||||
for (i = length; i; --i)
|
||||
d.dest[d.destLen++] = d.source[d.sourceIndex++];
|
||||
|
||||
/* make sure we start next block on a byte boundary */
|
||||
d.bitcount = 0;
|
||||
|
||||
return TINF_OK;
|
||||
}
|
||||
|
||||
/* inflate stream from source to dest */
|
||||
function tinf_uncompress(source, dest) {
|
||||
var d = new Data(source, dest);
|
||||
var bfinal, btype, res;
|
||||
|
||||
do {
|
||||
/* read final block flag */
|
||||
bfinal = tinf_getbit(d);
|
||||
|
||||
/* read block type (2 bits) */
|
||||
btype = tinf_read_bits(d, 2, 0);
|
||||
|
||||
/* decompress block */
|
||||
switch (btype) {
|
||||
case 0:
|
||||
/* decompress uncompressed block */
|
||||
res = tinf_inflate_uncompressed_block(d);
|
||||
break;
|
||||
case 1:
|
||||
/* decompress block with fixed huffman trees */
|
||||
res = tinf_inflate_block_data(d, sltree, sdtree);
|
||||
break;
|
||||
case 2:
|
||||
/* decompress block with dynamic huffman trees */
|
||||
tinf_decode_trees(d, d.ltree, d.dtree);
|
||||
res = tinf_inflate_block_data(d, d.ltree, d.dtree);
|
||||
break;
|
||||
default:
|
||||
res = TINF_DATA_ERROR;
|
||||
}
|
||||
|
||||
if (res !== TINF_OK)
|
||||
throw new Error('Data error');
|
||||
|
||||
} while (!bfinal);
|
||||
|
||||
if (d.destLen < d.dest.length) {
|
||||
if (typeof d.dest.slice === 'function')
|
||||
return d.dest.slice(0, d.destLen);
|
||||
else
|
||||
return d.dest.subarray(0, d.destLen);
|
||||
}
|
||||
|
||||
return d.dest;
|
||||
}
|
||||
|
||||
/* -------------------- *
|
||||
* -- initialization -- *
|
||||
* -------------------- */
|
||||
|
||||
/* build fixed huffman trees */
|
||||
tinf_build_fixed_trees(sltree, sdtree);
|
||||
|
||||
/* build extra bits and base tables */
|
||||
tinf_build_bits_base(length_bits, length_base, 4, 3);
|
||||
tinf_build_bits_base(dist_bits, dist_base, 2, 1);
|
||||
|
||||
/* fix a special case */
|
||||
length_bits[28] = 0;
|
||||
length_base[28] = 258;
|
||||
|
||||
//module.exports = tinf_uncompress;
|
||||
export const inflate = tinf_uncompress;
|
@ -146,8 +146,6 @@ export class CDPSession {
|
||||
this.websocket.onerror = (error) => {
|
||||
console.log(`WARN: WebSocket error - ${ JSON.stringify(error) }`);
|
||||
};
|
||||
|
||||
//this.send("Target.setDiscoverTargets", { discover: true });
|
||||
}
|
||||
|
||||
get target(): string {
|
||||
@ -196,9 +194,6 @@ export type Options = {
|
||||
};
|
||||
|
||||
|
||||
//function transform(source: string): string {
|
||||
//}
|
||||
|
||||
const TestData = (function() {
|
||||
function load(tag: string): any {
|
||||
const filename = resolve("testcases", tag + ".json.gz");
|
||||
@ -229,8 +224,6 @@ const TestData = (function() {
|
||||
|
||||
|
||||
export function start(_root: string, options: Options): Promise<Server> {
|
||||
//if (_root == null) { throw new Error("root required"); }
|
||||
//const root = resolve(_root);
|
||||
|
||||
if (options == null) { options = { }; }
|
||||
if (options.port == null) { options.port = 8000; }
|
||||
@ -242,14 +235,14 @@ export function start(_root: string, options: Options): Promise<Server> {
|
||||
|
||||
let filename: string;
|
||||
if (url === "/") {
|
||||
filename = "./output/index.html";
|
||||
filename = "./misc/test-browser/index.html";
|
||||
} else if (url === "/ethers.js" || url === "/index.js") {
|
||||
filename = "./dist/ethers.js";
|
||||
} else if (url === "/ethers.js.map") {
|
||||
filename = "./dist/ethers.js.map";
|
||||
|
||||
} else if (url.startsWith("/static/")) {
|
||||
filename = "./output/" + url.substring(8);
|
||||
filename = "./misc/test-browser/" + url.substring(8);
|
||||
|
||||
} else if (url === "/tests/utils.js") {
|
||||
//console.log({ status: 200, content: `<<in-memory ${ TestData.length } bytes>>` });
|
||||
@ -341,7 +334,15 @@ export function start(_root: string, options: Options): Promise<Server> {
|
||||
(async function() {
|
||||
await start(resolve("."), { port: 8000 });
|
||||
|
||||
const cmd = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
||||
const cmds = [
|
||||
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
||||
"/usr/bin/chromium"
|
||||
].filter((f) => { try { fs.accessSync(f); return true; } catch (error) { return false; } });
|
||||
|
||||
if (cmds.length === 0) { throw new Error("no installed browser found"); }
|
||||
|
||||
const cmd = cmds[0];
|
||||
|
||||
const args = [ "--headless", "--disable-gpu", "--remote-debugging-port=8022" ];
|
||||
const browser = child_process.spawn(cmd, args);
|
||||
|
||||
@ -361,16 +362,15 @@ export function start(_root: string, options: Options): Promise<Server> {
|
||||
}
|
||||
});
|
||||
});
|
||||
console.log(url);
|
||||
//url = "ws://127.0.0.1:8022/devtools/browser/e02e20e9-3e5f-47f6-bc23-1c050acc6da6";
|
||||
console.log("URL:", url);
|
||||
|
||||
const session = new CDPSession(url);
|
||||
// "ws://127.0.0.1:8022/devtools/browser/cab84776-4714-4a0f-aae3-acec84feddd9");
|
||||
await session.ready;
|
||||
await session.send("Console.enable", { });
|
||||
await session.navigate("http:/\/localhost:8000");
|
||||
|
||||
const status = await session.done;
|
||||
console.log(status);
|
||||
console.log("STATUS:", status);
|
||||
process.exit(status);
|
||||
})();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user