sqlmath 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitconfig +2 -2
- package/.github/workflows/ci.yml +73 -15
- package/.github/workflows/publish.yml +66 -0
- package/.gitignore +1 -5
- package/CHANGELOG.md +53 -2
- package/LICENSE +16 -22
- package/README.md +18 -219
- package/asset_image_folder_open_solid.svg +1 -0
- package/jslint.mjs +10998 -0
- package/jslint_ci.sh +1542 -728
- package/package.json +23 -8
- package/{sqlite-autoconf-3360000/sqlite3.c → sqlite3.c} +13116 -85
- package/sqlite3_ext.c +8372 -0
- package/{sqlite-autoconf-3360000/shell.c → sqlite3_shell.c} +330 -275
- package/sqlmath.mjs +1713 -0
- package/sqlmath_base.c +1832 -0
- package/sqlmath_custom.c +78 -0
- package/sqlmath_custom.cpp +0 -0
- package/sqlmath_custom.mjs +4 -0
- package/sqlmath_old.js +31038 -0
- package/extension-functions.c +0 -2047
- package/node_sqlite3.cc +0 -11877
- package/sqlite-autoconf-3360000/INSTALL +0 -370
- package/sqlite-autoconf-3360000/Makefile.am +0 -20
- package/sqlite-autoconf-3360000/Makefile.fallback +0 -19
- package/sqlite-autoconf-3360000/Makefile.in +0 -1028
- package/sqlite-autoconf-3360000/Makefile.msc +0 -1037
- package/sqlite-autoconf-3360000/README.txt +0 -113
- package/sqlite-autoconf-3360000/Replace.cs +0 -223
- package/sqlite-autoconf-3360000/aclocal.m4 +0 -10199
- package/sqlite-autoconf-3360000/compile +0 -347
- package/sqlite-autoconf-3360000/config.guess +0 -1480
- package/sqlite-autoconf-3360000/config.sub +0 -1801
- package/sqlite-autoconf-3360000/configure +0 -16135
- package/sqlite-autoconf-3360000/configure.ac +0 -285
- package/sqlite-autoconf-3360000/depcomp +0 -791
- package/sqlite-autoconf-3360000/install-sh +0 -508
- package/sqlite-autoconf-3360000/ltmain.sh +0 -11156
- package/sqlite-autoconf-3360000/missing +0 -215
- package/sqlite-autoconf-3360000/sqlite3.1 +0 -286
- package/sqlite-autoconf-3360000/sqlite3.h +0 -12353
- package/sqlite-autoconf-3360000/sqlite3.pc.in +0 -13
- package/sqlite-autoconf-3360000/sqlite3.rc +0 -83
- package/sqlite-autoconf-3360000/sqlite3ext.h +0 -663
- package/sqlite-autoconf-3360000/sqlite3rc.h +0 -3
- package/sqlite-autoconf-3360000/tea/Makefile.in +0 -440
- package/sqlite-autoconf-3360000/tea/README +0 -36
- package/sqlite-autoconf-3360000/tea/aclocal.m4 +0 -9
- package/sqlite-autoconf-3360000/tea/configure +0 -9989
- package/sqlite-autoconf-3360000/tea/configure.ac +0 -201
- package/sqlite-autoconf-3360000/tea/doc/sqlite3.n +0 -15
- package/sqlite-autoconf-3360000/tea/generic/tclsqlite3.c +0 -4016
- package/sqlite-autoconf-3360000/tea/license.terms +0 -6
- package/sqlite-autoconf-3360000/tea/pkgIndex.tcl.in +0 -7
- package/sqlite-autoconf-3360000/tea/tclconfig/install-sh +0 -528
- package/sqlite-autoconf-3360000/tea/tclconfig/tcl.m4 +0 -4168
- package/sqlite-autoconf-3360000/tea/win/makefile.vc +0 -419
- package/sqlite-autoconf-3360000/tea/win/nmakehlp.c +0 -815
- package/sqlite-autoconf-3360000/tea/win/rules.vc +0 -711
- package/sqlmath.js +0 -238
- package/test/backup.test.js +0 -279
- package/test/blob.test.js +0 -54
- package/test/cache.test.js +0 -42
- package/test/constants.test.js +0 -44
- package/test/database_fail.test.js +0 -153
- package/test/each.test.js +0 -39
- package/test/exec.test.js +0 -39
- package/test/extension.test.js +0 -26
- package/test/extension_functions.test.js +0 -29
- package/test/fts-content.test.js +0 -13
- package/test/interrupt.test.js +0 -80
- package/test/issue-108.test.js +0 -28
- package/test/json.test.js +0 -22
- package/test/map.test.js +0 -63
- package/test/named_columns.test.js +0 -38
- package/test/named_params.test.js +0 -69
- package/test/null_error.test.js +0 -41
- package/test/nw/.gitignore +0 -3
- package/test/nw/Makefile +0 -39
- package/test/nw/index.html +0 -14
- package/test/nw/package.json +0 -9
- package/test/open_close.test.js +0 -187
- package/test/other_objects.test.js +0 -98
- package/test/parallel_insert.test.js +0 -44
- package/test/prepare.test.js +0 -427
- package/test/profile.test.js +0 -57
- package/test/rerun.test.js +0 -50
- package/test/scheduling.test.js +0 -44
- package/test/serialization.test.js +0 -104
- package/test/support/createdb-electron.js +0 -10
- package/test/support/createdb.js +0 -47
- package/test/support/elmo.png +0 -0
- package/test/support/helper.js +0 -37
- package/test/support/script.sql +0 -70
- package/test/trace.test.js +0 -67
- package/test/unicode.test.js +0 -114
- package/test/upsert.test.js +0 -27
- package/test/verbose.test.js +0 -60
- package/test.js +0 -141
- package/test.slr.mjs +0 -212
package/jslint_ci.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
|
|
6
6
|
|
|
7
7
|
# sh one-liner
|
|
8
|
-
#
|
|
8
|
+
# git add .; npm run test2; git checkout .
|
|
9
9
|
# git branch -d -r origin/aa
|
|
10
10
|
# git config --global diff.algorithm histogram
|
|
11
11
|
# git fetch origin alpha beta master && git fetch upstream alpha beta master
|
|
@@ -18,13 +18,131 @@
|
|
|
18
18
|
# ln -f jslint.mjs ~/jslint.mjs
|
|
19
19
|
# openssl rand -base64 32 # random key
|
|
20
20
|
# sh jslint_ci.sh shCiBranchPromote origin alpha beta
|
|
21
|
-
# sh jslint_ci.sh shRunWithScreenshotTxt .
|
|
21
|
+
# sh jslint_ci.sh shRunWithScreenshotTxt .artifact/screenshot_changelog.svg head -n50 CHANGELOG.md
|
|
22
22
|
# vim rgx-lowercase \L\1\e
|
|
23
23
|
|
|
24
|
+
shBashrcDebianInit() {
|
|
25
|
+
# this function will init debian:stable /etc/skel/.bashrc
|
|
26
|
+
# https://sources.debian.org/src/bash/4.4-5/debian/skel.bashrc/
|
|
27
|
+
# ~/.bashrc: executed by bash(1) for non-login shells.
|
|
28
|
+
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
|
|
29
|
+
# for examples
|
|
30
|
+
|
|
31
|
+
# If not running interactively, don't do anything
|
|
32
|
+
case $- in
|
|
33
|
+
*i*) ;;
|
|
34
|
+
*) return;;
|
|
35
|
+
esac
|
|
36
|
+
|
|
37
|
+
# don't put duplicate lines or lines starting with space in the history.
|
|
38
|
+
# See bash(1) for more options
|
|
39
|
+
HISTCONTROL=ignoreboth
|
|
40
|
+
|
|
41
|
+
# append to the history file, don't overwrite it
|
|
42
|
+
shopt -s histappend
|
|
43
|
+
|
|
44
|
+
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
|
|
45
|
+
HISTSIZE=1000
|
|
46
|
+
HISTFILESIZE=2000
|
|
47
|
+
|
|
48
|
+
# check the window size after each command and, if necessary,
|
|
49
|
+
# update the values of LINES and COLUMNS.
|
|
50
|
+
shopt -s checkwinsize
|
|
51
|
+
|
|
52
|
+
# If set, the pattern "**" used in a pathname expansion context will
|
|
53
|
+
# match all files and zero or more directories and subdirectories.
|
|
54
|
+
#shopt -s globstar
|
|
55
|
+
|
|
56
|
+
# make less more friendly for non-text input files, see lesspipe(1)
|
|
57
|
+
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
|
58
|
+
|
|
59
|
+
# set variable identifying the chroot you work in (used in the prompt below)
|
|
60
|
+
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
|
61
|
+
debian_chroot=$(cat /etc/debian_chroot)
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# set a fancy prompt (non-color, unless we know we "want" color)
|
|
65
|
+
case "$TERM" in
|
|
66
|
+
xterm-color|*-256color) color_prompt=yes;;
|
|
67
|
+
esac
|
|
68
|
+
|
|
69
|
+
# uncomment for a colored prompt, if the terminal has the capability; turned
|
|
70
|
+
# off by default to not distract the user: the focus in a terminal window
|
|
71
|
+
# should be on the output of commands, not on the prompt
|
|
72
|
+
#force_color_prompt=yes
|
|
73
|
+
|
|
74
|
+
if [ -n "$force_color_prompt" ]; then
|
|
75
|
+
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
|
76
|
+
# We have color support; assume it's compliant with Ecma-48
|
|
77
|
+
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
|
78
|
+
# a case would tend to support setf rather than setaf.)
|
|
79
|
+
color_prompt=yes
|
|
80
|
+
else
|
|
81
|
+
color_prompt=
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [ "$color_prompt" = yes ]; then
|
|
86
|
+
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
|
|
87
|
+
else
|
|
88
|
+
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
|
89
|
+
fi
|
|
90
|
+
unset color_prompt force_color_prompt
|
|
91
|
+
|
|
92
|
+
# If this is an xterm set the title to user@host:dir
|
|
93
|
+
case "$TERM" in
|
|
94
|
+
xterm*|rxvt*)
|
|
95
|
+
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
|
|
96
|
+
;;
|
|
97
|
+
*)
|
|
98
|
+
;;
|
|
99
|
+
esac
|
|
100
|
+
|
|
101
|
+
# enable color support of ls and also add handy aliases
|
|
102
|
+
if [ -x /usr/bin/dircolors ]; then
|
|
103
|
+
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
|
|
104
|
+
alias ls='ls --color=auto'
|
|
105
|
+
#alias dir='dir --color=auto'
|
|
106
|
+
#alias vdir='vdir --color=auto'
|
|
107
|
+
|
|
108
|
+
alias grep='grep --color=auto'
|
|
109
|
+
#alias fgrep='fgrep --color=auto'
|
|
110
|
+
#alias egrep='egrep --color=auto'
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# colored GCC warnings and errors
|
|
114
|
+
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
|
|
115
|
+
|
|
116
|
+
# some more ls aliases
|
|
117
|
+
alias ll='ls -alF'
|
|
118
|
+
#alias la='ls -A'
|
|
119
|
+
#alias l='ls -CF'
|
|
120
|
+
|
|
121
|
+
# Alias definitions.
|
|
122
|
+
# You may want to put all your additions into a separate file like
|
|
123
|
+
# ~/.bash_aliases, instead of adding them here directly.
|
|
124
|
+
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
|
|
125
|
+
|
|
126
|
+
if [ -f ~/.bash_aliases ]; then
|
|
127
|
+
. ~/.bash_aliases
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# enable programmable completion features (you don't need to enable
|
|
131
|
+
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
|
|
132
|
+
# sources /etc/bash.bashrc).
|
|
133
|
+
if ! shopt -oq posix; then
|
|
134
|
+
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
|
135
|
+
. /usr/share/bash-completion/bash_completion
|
|
136
|
+
elif [ -f /etc/bash_completion ]; then
|
|
137
|
+
. /etc/bash_completion
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
140
|
+
}
|
|
141
|
+
|
|
24
142
|
shBrowserScreenshot() {(set -e
|
|
25
143
|
# this function will run headless-chrome to screenshot url $1 with
|
|
26
144
|
# window-size $2
|
|
27
|
-
node --input-type=module
|
|
145
|
+
node --input-type=module --eval '
|
|
28
146
|
import moduleChildProcess from "child_process";
|
|
29
147
|
import modulePath from "path";
|
|
30
148
|
import moduleUrl from "url";
|
|
@@ -41,7 +159,9 @@ import moduleUrl from "url";
|
|
|
41
159
|
return argList[0];
|
|
42
160
|
};
|
|
43
161
|
}());
|
|
44
|
-
(function () {
|
|
162
|
+
(async function () {
|
|
163
|
+
let child;
|
|
164
|
+
let exitCode;
|
|
45
165
|
let file;
|
|
46
166
|
let timeStart;
|
|
47
167
|
let url;
|
|
@@ -60,10 +180,10 @@ import moduleUrl from "url";
|
|
|
60
180
|
if (String(file + "/").startsWith(process.cwd() + "/")) {
|
|
61
181
|
file = file.replace(process.cwd(), "");
|
|
62
182
|
}
|
|
63
|
-
file = ".
|
|
183
|
+
file = ".artifact/screenshot_browser_" + encodeURIComponent(file).replace((
|
|
64
184
|
/%/g
|
|
65
185
|
), "_").toLowerCase() + ".png";
|
|
66
|
-
moduleChildProcess.spawn(
|
|
186
|
+
child = moduleChildProcess.spawn(
|
|
67
187
|
(
|
|
68
188
|
process.platform === "darwin"
|
|
69
189
|
? "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
@@ -96,71 +216,64 @@ import moduleUrl from "url";
|
|
|
96
216
|
"ignore", 1, 2
|
|
97
217
|
]
|
|
98
218
|
}
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
+ "\n - url - " + url
|
|
103
|
-
+ "\n - wrote - " + file
|
|
104
|
-
+ "\n - timeElapsed - " + (Date.now() - timeStart) + " ms"
|
|
105
|
-
+ "\n - EXIT_CODE=" + exitCode
|
|
106
|
-
);
|
|
219
|
+
);
|
|
220
|
+
exitCode = await new Promise(function (resolve) {
|
|
221
|
+
child.on("exit", resolve);
|
|
107
222
|
});
|
|
223
|
+
console.error(
|
|
224
|
+
"shBrowserScreenshot"
|
|
225
|
+
+ "\n - url - " + url
|
|
226
|
+
+ "\n - wrote - " + file
|
|
227
|
+
+ "\n - timeElapsed - " + (Date.now() - timeStart) + " ms"
|
|
228
|
+
+ "\n - EXIT_CODE=" + exitCode
|
|
229
|
+
);
|
|
108
230
|
}());
|
|
109
|
-
' "$@" #
|
|
231
|
+
' "$@" # '
|
|
110
232
|
)}
|
|
111
233
|
|
|
112
234
|
shCiArtifactUpload() {(set -e
|
|
113
235
|
# this function will upload build-artifacts to branch-gh-pages
|
|
114
236
|
local BRANCH
|
|
115
|
-
local
|
|
116
|
-
node --input-type=module
|
|
237
|
+
local FILE
|
|
238
|
+
node --input-type=module --eval '
|
|
117
239
|
process.exit(Number(
|
|
118
|
-
`${process.version.split(".")[0]}.${process.arch}.${process.platform}`
|
|
119
|
-
process.env.CI_NODE_VERSION_ARCH_PLATFORM
|
|
240
|
+
`${process.version.split(".")[0]}.${process.arch}.${process.platform}`
|
|
241
|
+
!== process.env.CI_NODE_VERSION_ARCH_PLATFORM
|
|
120
242
|
));
|
|
121
243
|
' || return 0
|
|
122
|
-
# init $BRANCH
|
|
123
|
-
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
124
|
-
git pull --unshallow origin "$BRANCH"
|
|
125
244
|
# init .git/config
|
|
126
245
|
git config --local user.email "github-actions@users.noreply.github.com"
|
|
127
246
|
git config --local user.name "github-actions"
|
|
128
|
-
#
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
247
|
+
# init $BRANCH
|
|
248
|
+
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
249
|
+
git pull --unshallow origin "$BRANCH"
|
|
250
|
+
# init $UPSTREAM_OWNER
|
|
251
|
+
export UPSTREAM_OWNER="${UPSTREAM_OWNER:-jslint-org}"
|
|
252
|
+
# init $UPSTREAM_REPO
|
|
253
|
+
export UPSTREAM_REPO="${UPSTREAM_REPO:-jslint}"
|
|
254
|
+
# screenshot changelog and files
|
|
255
|
+
node --input-type=module --eval '
|
|
135
256
|
import moduleChildProcess from "child_process";
|
|
136
|
-
(
|
|
137
|
-
let screenshotCurl = await moduleFs.promises.stat("jslint.mjs");
|
|
138
|
-
screenshotCurl = String(`
|
|
139
|
-
echo "\
|
|
140
|
-
% Total % Received % Xferd Average Speed Time Time Time Current
|
|
141
|
-
Dload Upload Total Spent Left Speed
|
|
142
|
-
100 250k 100 250k 0 0 250k 0 0:00:01 --:--:-- 0:00:01 250k\
|
|
143
|
-
"
|
|
144
|
-
`).trim().replace((
|
|
145
|
-
/250/g
|
|
146
|
-
), Math.floor(screenshotCurl.size / 1024));
|
|
257
|
+
(function () {
|
|
147
258
|
[
|
|
148
|
-
// parallel-task - screenshot files
|
|
149
|
-
[
|
|
150
|
-
"shRunWithScreenshotTxt",
|
|
151
|
-
".build/screenshot-files.svg",
|
|
152
|
-
"shGitLsTree"
|
|
153
|
-
],
|
|
154
259
|
// parallel-task - screenshot changelog
|
|
155
260
|
[
|
|
261
|
+
"jslint_ci.sh",
|
|
156
262
|
"shRunWithScreenshotTxt",
|
|
157
|
-
".
|
|
263
|
+
".artifact/screenshot_changelog.svg",
|
|
158
264
|
"head",
|
|
159
265
|
"-n50",
|
|
160
266
|
"CHANGELOG.md"
|
|
267
|
+
],
|
|
268
|
+
// parallel-task - screenshot files
|
|
269
|
+
[
|
|
270
|
+
"jslint_ci.sh",
|
|
271
|
+
"shRunWithScreenshotTxt",
|
|
272
|
+
".artifact/screenshot_package_listing.svg",
|
|
273
|
+
"shGitLsTree"
|
|
161
274
|
]
|
|
162
275
|
].forEach(function (argList) {
|
|
163
|
-
moduleChildProcess.spawn("
|
|
276
|
+
moduleChildProcess.spawn("sh", argList, {
|
|
164
277
|
stdio: [
|
|
165
278
|
"ignore", 1, 2
|
|
166
279
|
]
|
|
@@ -170,111 +283,26 @@ echo "\
|
|
|
170
283
|
}
|
|
171
284
|
});
|
|
172
285
|
});
|
|
173
|
-
// parallel-task - screenshot example-shell-commands in README.md
|
|
174
|
-
Array.from(String(
|
|
175
|
-
await moduleFs.promises.readFile("README.md", "utf8")
|
|
176
|
-
).matchAll(
|
|
177
|
-
/\n```shell\u0020<!--\u0020shRunWithScreenshotTxt\u0020(.*?)\u0020-->\n([\S\s]*?\n)```\n/g
|
|
178
|
-
)).forEach(async function ([
|
|
179
|
-
ignore, file, script
|
|
180
|
-
]) {
|
|
181
|
-
await moduleFs.promises.writeFile(file + ".sh", (
|
|
182
|
-
"printf \u0027"
|
|
183
|
-
+ script.trim().replace((
|
|
184
|
-
/[%\\]/gm
|
|
185
|
-
), "$&$&").replace((
|
|
186
|
-
/\u0027/g
|
|
187
|
-
), "\u0027\"\u0027\"\u0027").replace((
|
|
188
|
-
/^/gm
|
|
189
|
-
), "> ")
|
|
190
|
-
+ "\n\n\n\u0027\n"
|
|
191
|
-
+ script.replace(
|
|
192
|
-
"curl -L https://www.jslint.com/jslint.mjs > jslint.mjs",
|
|
193
|
-
screenshotCurl
|
|
194
|
-
)
|
|
195
|
-
));
|
|
196
|
-
moduleChildProcess.spawn(
|
|
197
|
-
"./jslint_ci.sh",
|
|
198
|
-
[
|
|
199
|
-
"shRunWithScreenshotTxt",
|
|
200
|
-
file,
|
|
201
|
-
"sh",
|
|
202
|
-
file + ".sh"
|
|
203
|
-
],
|
|
204
|
-
{
|
|
205
|
-
stdio: [
|
|
206
|
-
"ignore", 1, 2
|
|
207
|
-
]
|
|
208
|
-
}
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
}());
|
|
212
|
-
' # '
|
|
213
|
-
# seo - inline css-assets and invalidate cached-assets
|
|
214
|
-
node --input-type=module -e '
|
|
215
|
-
import moduleFs from "fs";
|
|
216
|
-
(async function () {
|
|
217
|
-
let cacheKey = Math.random().toString(36).slice(-4);
|
|
218
|
-
let fileDict = {};
|
|
219
|
-
await Promise.all([
|
|
220
|
-
"asset-codemirror-rollup.css",
|
|
221
|
-
"browser.mjs",
|
|
222
|
-
"index.html"
|
|
223
|
-
].map(async function (file) {
|
|
224
|
-
fileDict[file] = await moduleFs.promises.readFile(file, "utf8");
|
|
225
|
-
}));
|
|
226
|
-
|
|
227
|
-
// Inline css-assets.
|
|
228
|
-
|
|
229
|
-
fileDict["index.html"] = fileDict["index.html"].replace((
|
|
230
|
-
"\n<link rel=\"stylesheet\" href=\"asset-codemirror-rollup.css\">\n"
|
|
231
|
-
), function () {
|
|
232
|
-
return (
|
|
233
|
-
"\n<style>\n"
|
|
234
|
-
+ fileDict["asset-codemirror-rollup.css"].trim()
|
|
235
|
-
+ "\n</style>\n"
|
|
236
|
-
);
|
|
237
|
-
});
|
|
238
|
-
fileDict["index.html"] = fileDict["index.html"].replace((
|
|
239
|
-
"\n<style class=\"JSLINT_REPORT_STYLE\"></style>\n"
|
|
240
|
-
), function () {
|
|
241
|
-
return fileDict["browser.mjs"].match(
|
|
242
|
-
/\n<style\sclass="JSLINT_REPORT_STYLE">\n[\S\s]*?\n<\/style>\n/
|
|
243
|
-
)[0];
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// Invalidate cached-assets.
|
|
247
|
-
|
|
248
|
-
fileDict["browser.mjs"] = fileDict["browser.mjs"].replace((
|
|
249
|
-
/^import\u0020.+?\u0020from\u0020".+?\.(?:js|mjs)\b/gm
|
|
250
|
-
), function (match0) {
|
|
251
|
-
return `${match0}?cc=${cacheKey}`;
|
|
252
|
-
});
|
|
253
|
-
fileDict["index.html"] = fileDict["index.html"].replace((
|
|
254
|
-
/\b(?:href|src)=".+?\.(?:css|js|mjs)\b/g
|
|
255
|
-
), function (match0) {
|
|
256
|
-
return `${match0}?cc=${cacheKey}`;
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// Write file.
|
|
260
|
-
|
|
261
|
-
await Promise.all(Object.entries(fileDict).map(function ([
|
|
262
|
-
file, data
|
|
263
|
-
]) {
|
|
264
|
-
moduleFs.promises.writeFile(file, data);
|
|
265
|
-
}));
|
|
266
286
|
}());
|
|
267
|
-
' # '
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
287
|
+
' "$@" # '
|
|
288
|
+
shCiArtifactUploadCustom
|
|
289
|
+
# 1px-border around browser-screenshot
|
|
290
|
+
if (ls .artifact/screenshot_browser_*.png 2>/dev/null \
|
|
291
|
+
&& mogrify -version 2>&1 | grep -i imagemagick)
|
|
292
|
+
then
|
|
293
|
+
mogrify -shave 1x1 -bordercolor black -border 1 \
|
|
294
|
+
.artifact/screenshot_browser_*.png
|
|
295
|
+
fi
|
|
296
|
+
# add dir .artifact
|
|
297
|
+
git add -f .artifact
|
|
298
|
+
git rm --cached -r .artifact/tmp 2>/dev/null || true
|
|
299
|
+
git commit -am "add dir .artifact"
|
|
271
300
|
# checkout branch-gh-pages
|
|
272
|
-
git checkout -b gh-pages
|
|
273
301
|
git fetch origin gh-pages
|
|
274
|
-
git
|
|
302
|
+
git checkout -b gh-pages origin/gh-pages
|
|
275
303
|
# update dir branch-$BRANCH
|
|
276
304
|
rm -rf "branch-$BRANCH"
|
|
277
|
-
mkdir "branch-$BRANCH"
|
|
305
|
+
mkdir -p "branch-$BRANCH"
|
|
278
306
|
(set -e
|
|
279
307
|
cd "branch-$BRANCH"
|
|
280
308
|
git init -b branch1
|
|
@@ -285,22 +313,31 @@ import moduleFs from "fs";
|
|
|
285
313
|
# update root-dir with branch-beta
|
|
286
314
|
if [ "$BRANCH" = beta ]
|
|
287
315
|
then
|
|
288
|
-
|
|
316
|
+
rm -rf .artifact
|
|
289
317
|
git checkout beta .
|
|
318
|
+
# update apidoc.html
|
|
319
|
+
for FILE in apidoc.html
|
|
320
|
+
do
|
|
321
|
+
if [ -f ".artifact/$FILE" ]
|
|
322
|
+
then
|
|
323
|
+
cp -a ".artifact/$FILE" .
|
|
324
|
+
git add -f "$FILE"
|
|
325
|
+
fi
|
|
326
|
+
done
|
|
290
327
|
fi
|
|
291
328
|
# update README.md with branch-$BRANCH and $GITHUB_REPOSITORY
|
|
292
329
|
sed -i \
|
|
293
330
|
-e "s|/branch-[0-9A-Z_a-z]*/|/branch-$BRANCH/|g" \
|
|
294
|
-
-e "s|\
|
|
295
|
-
-e "s|\
|
|
331
|
+
-e "s|\b$UPSTREAM_OWNER/$UPSTREAM_REPO\b|$GITHUB_REPOSITORY|g" \
|
|
332
|
+
-e "s|\b$UPSTREAM_OWNER\.github\.io/$UPSTREAM_REPO\b|$(
|
|
296
333
|
printf "$GITHUB_REPOSITORY" | sed -e "s|/|.github.io/|"
|
|
297
334
|
)|g" \
|
|
298
335
|
"branch-$BRANCH/README.md"
|
|
299
336
|
git status
|
|
300
337
|
git commit -am "update dir branch-$BRANCH" || true
|
|
301
|
-
# if branch-gh-pages has more than
|
|
338
|
+
# if branch-gh-pages has more than 50 commits,
|
|
302
339
|
# then backup and squash commits
|
|
303
|
-
if [ "$(git rev-list --count gh-pages)" -gt
|
|
340
|
+
if [ "$(git rev-list --count gh-pages)" -gt 50 ]
|
|
304
341
|
then
|
|
305
342
|
# backup
|
|
306
343
|
shGitCmdWithGithubToken push origin -f gh-pages:gh-pages-backup
|
|
@@ -325,8 +362,65 @@ import moduleFs from "fs";
|
|
|
325
362
|
)
|
|
326
363
|
)}
|
|
327
364
|
|
|
365
|
+
shCiArtifactUploadCustom() {(set -e
|
|
366
|
+
# this function will run custom-code to upload build-artifacts
|
|
367
|
+
return
|
|
368
|
+
)}
|
|
369
|
+
|
|
328
370
|
shCiBase() {(set -e
|
|
329
371
|
# this function will run base-ci
|
|
372
|
+
# update table-of-contents in README.md
|
|
373
|
+
node --input-type=module --eval '
|
|
374
|
+
import moduleFs from "fs";
|
|
375
|
+
(async function () {
|
|
376
|
+
let data = await moduleFs.promises.readFile("README.md", "utf8");
|
|
377
|
+
data = data.replace((
|
|
378
|
+
/\n# Table of Contents$[\S\s]*?\n\n\n/m
|
|
379
|
+
), function () {
|
|
380
|
+
let ii = -1;
|
|
381
|
+
let toc = "\n# Table of Contents\n";
|
|
382
|
+
data.replace((
|
|
383
|
+
// /(\n{3,}#|\n+?<br><br>\n#|\n+?###) (\S.*)/g
|
|
384
|
+
/((?:\n{3,}|\n+?(?:<br>)+?\n)(?:#|###)) (\S.*)/g
|
|
385
|
+
), function (match0, level, title) {
|
|
386
|
+
if (title === "Table of Contents") {
|
|
387
|
+
ii += 1;
|
|
388
|
+
return "";
|
|
389
|
+
}
|
|
390
|
+
if (ii < 0) {
|
|
391
|
+
return "";
|
|
392
|
+
}
|
|
393
|
+
switch (level) {
|
|
394
|
+
case "\n\n\n<br><br>\n#":
|
|
395
|
+
ii += 1;
|
|
396
|
+
toc += "\n" + ii + ". [" + title + "](#";
|
|
397
|
+
break;
|
|
398
|
+
case "\n\n\n<br><br>\n###":
|
|
399
|
+
toc += " - [" + title + "](#";
|
|
400
|
+
break;
|
|
401
|
+
default:
|
|
402
|
+
throw new Error(JSON.stringify(match0));
|
|
403
|
+
}
|
|
404
|
+
toc += title.toLowerCase().replace((
|
|
405
|
+
/[^ \-0-9A-Z_a-z]/g
|
|
406
|
+
), "").replace((
|
|
407
|
+
/ /g
|
|
408
|
+
), "-") + ")\n";
|
|
409
|
+
return "";
|
|
410
|
+
});
|
|
411
|
+
toc += "\n\n";
|
|
412
|
+
return toc;
|
|
413
|
+
});
|
|
414
|
+
await moduleFs.promises.writeFile("README.md", data);
|
|
415
|
+
}());
|
|
416
|
+
' "$@" # '
|
|
417
|
+
shCiBaseCustom
|
|
418
|
+
git diff
|
|
419
|
+
)}
|
|
420
|
+
|
|
421
|
+
shCiBaseCustom() {(set -e
|
|
422
|
+
# this function will run custom-ci
|
|
423
|
+
return
|
|
330
424
|
)}
|
|
331
425
|
|
|
332
426
|
shCiBranchPromote() {(set -e
|
|
@@ -344,9 +438,15 @@ shCiBranchPromote() {(set -e
|
|
|
344
438
|
git push "$REMOTE" "$REMOTE/$BRANCH1:$BRANCH2" "$@"
|
|
345
439
|
)}
|
|
346
440
|
|
|
441
|
+
shCiNpmPublishCustom() {(set -e
|
|
442
|
+
# this function will run custom-code to npm-publish package
|
|
443
|
+
npm install
|
|
444
|
+
npm publish --access public
|
|
445
|
+
)}
|
|
446
|
+
|
|
347
447
|
shDirHttplinkValidate() {(set -e
|
|
348
448
|
# this function will validate http-links embedded in .html and .md files
|
|
349
|
-
node --input-type=module
|
|
449
|
+
node --input-type=module --eval '
|
|
350
450
|
import moduleFs from "fs";
|
|
351
451
|
import moduleHttps from "https";
|
|
352
452
|
import moduleUrl from "url";
|
|
@@ -356,7 +456,7 @@ import moduleUrl from "url";
|
|
|
356
456
|
await moduleFs.promises.readdir(".")
|
|
357
457
|
).forEach(async function (file) {
|
|
358
458
|
let data;
|
|
359
|
-
if (!(
|
|
459
|
+
if (file === "CHANGELOG.md" || !(
|
|
360
460
|
/.\.html$|.\.md$/m
|
|
361
461
|
).test(file)) {
|
|
362
462
|
return;
|
|
@@ -437,7 +537,12 @@ import moduleUrl from "url";
|
|
|
437
537
|
});
|
|
438
538
|
});
|
|
439
539
|
}());
|
|
440
|
-
' #
|
|
540
|
+
' "$@" # '
|
|
541
|
+
)}
|
|
542
|
+
|
|
543
|
+
shDuList() {(set -e
|
|
544
|
+
# this function will du $1 and sort its subdir by size
|
|
545
|
+
du -md1 "$1" | sort -nr
|
|
441
546
|
)}
|
|
442
547
|
|
|
443
548
|
shGitCmdWithGithubToken() {(set -e
|
|
@@ -462,12 +567,44 @@ shGitCmdWithGithubToken() {(set -e
|
|
|
462
567
|
return "$EXIT_CODE"
|
|
463
568
|
)}
|
|
464
569
|
|
|
570
|
+
shGitGc() {(set -e
|
|
571
|
+
# this function will gc unreachable .git objects
|
|
572
|
+
# http://stackoverflow.com/questions/3797907/how-to-remove-unused-objects-from-a-git-repository
|
|
573
|
+
git \
|
|
574
|
+
-c gc.reflogExpire=0 \
|
|
575
|
+
-c gc.reflogExpireUnreachable=0 \
|
|
576
|
+
-c gc.rerereresolved=0 \
|
|
577
|
+
-c gc.rerereunresolved=0 \
|
|
578
|
+
-c gc.pruneExpire=now \
|
|
579
|
+
gc
|
|
580
|
+
)}
|
|
581
|
+
|
|
582
|
+
shGitInitBase() {(set -e
|
|
583
|
+
# this function will git init && create basic git-template from jslint-org/base
|
|
584
|
+
local BRANCH
|
|
585
|
+
git init
|
|
586
|
+
git config core.autocrlf input
|
|
587
|
+
git remote remove base 2>/dev/null || true
|
|
588
|
+
git remote add base https://github.com/jslint-org/base
|
|
589
|
+
git fetch base base
|
|
590
|
+
for BRANCH in base alpha
|
|
591
|
+
do
|
|
592
|
+
git branch -D "$BRANCH" 2>/dev/null || true
|
|
593
|
+
git checkout -b "$BRANCH" base/base
|
|
594
|
+
done
|
|
595
|
+
sed -i.bak "s|owner/repo|${1:-owner/repo}|" .gitconfig
|
|
596
|
+
rm .gitconfig.bak
|
|
597
|
+
cp .gitconfig .git/config
|
|
598
|
+
git commit -am "update owner/repo to $1" || true
|
|
599
|
+
)}
|
|
600
|
+
|
|
601
|
+
|
|
465
602
|
shGitLsTree() {(set -e
|
|
466
603
|
# this function will "git ls-tree" all files committed in HEAD
|
|
467
604
|
# example use:
|
|
468
605
|
# shGitLsTree | sort -rk3 # sort by date
|
|
469
606
|
# shGitLsTree | sort -rk4 # sort by size
|
|
470
|
-
node --input-type=module
|
|
607
|
+
node --input-type=module --eval '
|
|
471
608
|
import moduleChildProcess from "child_process";
|
|
472
609
|
(async function () {
|
|
473
610
|
let result;
|
|
@@ -488,7 +625,7 @@ import moduleChildProcess from "child_process";
|
|
|
488
625
|
}).setEncoding("utf8");
|
|
489
626
|
});
|
|
490
627
|
result = Array.from(result.matchAll(
|
|
491
|
-
/^(\S+?)
|
|
628
|
+
/^(\S+?) +?\S+? +?\S+? +?(\S+?)\t(\S+?)$/gm
|
|
492
629
|
)).map(function ([
|
|
493
630
|
ignore, mode, size, file
|
|
494
631
|
]) {
|
|
@@ -541,7 +678,82 @@ import moduleChildProcess from "child_process";
|
|
|
541
678
|
}).join(""));
|
|
542
679
|
});
|
|
543
680
|
}());
|
|
544
|
-
' #
|
|
681
|
+
' "$@" # '
|
|
682
|
+
)}
|
|
683
|
+
|
|
684
|
+
shGitSquashPop() {(set -e
|
|
685
|
+
# this function will squash HEAD to given $COMMIT
|
|
686
|
+
# http://stackoverflow.com/questions/5189560
|
|
687
|
+
# /how-can-i-squash-my-last-x-commits-together-using-git
|
|
688
|
+
COMMIT="$1"
|
|
689
|
+
MESSAGE="$2"
|
|
690
|
+
# reset git to previous $COMMIT
|
|
691
|
+
git reset "$COMMIT"
|
|
692
|
+
git add .
|
|
693
|
+
# commit HEAD immediately after previous $COMMIT
|
|
694
|
+
git commit -am "$MESSAGE" || true
|
|
695
|
+
)}
|
|
696
|
+
|
|
697
|
+
shGrep() {(set -e
|
|
698
|
+
# this function will recursively grep . for $REGEXP
|
|
699
|
+
REGEXP="$1"
|
|
700
|
+
shift
|
|
701
|
+
FILE_FILTER="\
|
|
702
|
+
/\\.|~$|/(obj|release)/|(\\b|_)(\\.\\d|\
|
|
703
|
+
archive|artifact|\
|
|
704
|
+
bower_component|build|\
|
|
705
|
+
coverage|\
|
|
706
|
+
doc|\
|
|
707
|
+
external|\
|
|
708
|
+
fixture|\
|
|
709
|
+
git_module|\
|
|
710
|
+
jquery|\
|
|
711
|
+
log|\
|
|
712
|
+
min|misc|mock|\
|
|
713
|
+
node_module|\
|
|
714
|
+
old|\
|
|
715
|
+
raw|\rollup|\
|
|
716
|
+
swp|\
|
|
717
|
+
tmp|\
|
|
718
|
+
vendor)s{0,1}(\\b|_)\
|
|
719
|
+
"
|
|
720
|
+
find . -type f |
|
|
721
|
+
grep -v -E "$FILE_FILTER" |
|
|
722
|
+
tr "\n" "\000" |
|
|
723
|
+
xargs -0 grep -HIin -E "$REGEXP" "$@" |
|
|
724
|
+
tee /tmp/shGrep.txt || true
|
|
725
|
+
)}
|
|
726
|
+
|
|
727
|
+
shGrepReplace() {(set -e
|
|
728
|
+
# this function will inline grep-and-replace /tmp/shGrep.txt
|
|
729
|
+
node --input-type=module --eval '
|
|
730
|
+
import moduleFs from "fs";
|
|
731
|
+
import moduleOs from "os";
|
|
732
|
+
import modulePath from "path";
|
|
733
|
+
(async function () {
|
|
734
|
+
"use strict";
|
|
735
|
+
let data;
|
|
736
|
+
let dict = {};
|
|
737
|
+
data = await moduleFs.promises.readFile((
|
|
738
|
+
moduleOs.tmpdir() + "/shGrep.txt"
|
|
739
|
+
), "utf8");
|
|
740
|
+
data = data.replace((
|
|
741
|
+
/^(.+?):(\d+?):(.*?)$/gm
|
|
742
|
+
), function (ignore, file, lineno, str) {
|
|
743
|
+
dict[file] = dict[file] || moduleFs.readFileSync( //jslint-quiet
|
|
744
|
+
modulePath.resolve(file),
|
|
745
|
+
"utf8"
|
|
746
|
+
).split("\n");
|
|
747
|
+
dict[file][lineno - 1] = str;
|
|
748
|
+
return "";
|
|
749
|
+
});
|
|
750
|
+
Object.entries(dict).forEach(function ([
|
|
751
|
+
file, data
|
|
752
|
+
]) {
|
|
753
|
+
moduleFs.promises.writeFile(file, data.join("\n"));
|
|
754
|
+
});
|
|
755
|
+
}());
|
|
756
|
+
' "$@" # '
|
|
545
757
|
)}
|
|
546
758
|
|
|
547
759
|
shHttpFileServer() {(set -e
|
|
@@ -569,7 +781,7 @@ shHttpFileServer() {(set -e
|
|
|
569
781
|
done
|
|
570
782
|
return
|
|
571
783
|
fi
|
|
572
|
-
node --input-type=module
|
|
784
|
+
node --input-type=module --eval '
|
|
573
785
|
import moduleChildProcess from "child_process";
|
|
574
786
|
import moduleFs from "fs";
|
|
575
787
|
import moduleHttp from "http";
|
|
@@ -590,9 +802,9 @@ import moduleUrl from "url";
|
|
|
590
802
|
};
|
|
591
803
|
}());
|
|
592
804
|
(async function httpFileServer() {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
805
|
+
|
|
806
|
+
// this function will start http-file-server
|
|
807
|
+
|
|
596
808
|
let contentTypeDict = {
|
|
597
809
|
".bmp": "image/bmp",
|
|
598
810
|
".cjs": "application/javascript; charset=utf-8",
|
|
@@ -636,10 +848,10 @@ import moduleUrl from "url";
|
|
|
636
848
|
return;
|
|
637
849
|
}
|
|
638
850
|
console.error(
|
|
639
|
-
"serverLog - "
|
|
640
|
-
new Date(timeStart).toISOString() + " - "
|
|
641
|
-
(Date.now() - timeStart) + "ms - "
|
|
642
|
-
(res.statusCode || 0) + " " + req.method + " " + pathname
|
|
851
|
+
"serverLog - "
|
|
852
|
+
+ new Date(timeStart).toISOString() + " - "
|
|
853
|
+
+ (Date.now() - timeStart) + "ms - "
|
|
854
|
+
+ (res.statusCode || 0) + " " + req.method + " " + pathname
|
|
643
855
|
);
|
|
644
856
|
});
|
|
645
857
|
// debug - echo request
|
|
@@ -678,9 +890,9 @@ import moduleUrl from "url";
|
|
|
678
890
|
}).listen(process.env.PORT);
|
|
679
891
|
}());
|
|
680
892
|
(function jslintDir() {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
893
|
+
|
|
894
|
+
// this function will jslint current-directory
|
|
895
|
+
|
|
684
896
|
moduleFs.stat((
|
|
685
897
|
process.env.HOME + "/jslint.mjs"
|
|
686
898
|
), function (ignore, exists) {
|
|
@@ -696,9 +908,9 @@ import moduleUrl from "url";
|
|
|
696
908
|
});
|
|
697
909
|
}());
|
|
698
910
|
(function replStart() {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
911
|
+
|
|
912
|
+
// this function will start repl-debugger
|
|
913
|
+
|
|
702
914
|
let that;
|
|
703
915
|
// start repl
|
|
704
916
|
that = moduleRepl.start({
|
|
@@ -715,7 +927,7 @@ import moduleUrl from "url";
|
|
|
715
927
|
// hook custom-eval-function
|
|
716
928
|
that.eval = function (script, context, file, onError) {
|
|
717
929
|
script.replace((
|
|
718
|
-
/^(\S+)
|
|
930
|
+
/^(\S+) (.*?)\n/
|
|
719
931
|
), function (ignore, match1, match2) {
|
|
720
932
|
switch (match1) {
|
|
721
933
|
// syntax-sugar - run shell-cmd
|
|
@@ -735,7 +947,7 @@ import moduleUrl from "url";
|
|
|
735
947
|
break;
|
|
736
948
|
}
|
|
737
949
|
match2 = match2.replace((
|
|
738
|
-
/^git
|
|
950
|
+
/^git /
|
|
739
951
|
), "git --no-pager ");
|
|
740
952
|
// run shell-cmd
|
|
741
953
|
console.error("$ " + match2);
|
|
@@ -756,8 +968,8 @@ import moduleUrl from "url";
|
|
|
756
968
|
console.error(
|
|
757
969
|
match2.split("").map(function (chr) {
|
|
758
970
|
return (
|
|
759
|
-
"\\u"
|
|
760
|
-
chr.charCodeAt(0).toString(16).padStart(4, 0)
|
|
971
|
+
"\\u"
|
|
972
|
+
+ chr.charCodeAt(0).toString(16).padStart(4, 0)
|
|
761
973
|
);
|
|
762
974
|
}).join("")
|
|
763
975
|
);
|
|
@@ -772,15 +984,15 @@ import moduleUrl from "url";
|
|
|
772
984
|
// console.error(Object.keys(global).map(function(key){return(typeof global[key]===\u0027object\u0027&&global[key]&&global[key]===global[key]?\u0027global\u0027:typeof global[key])+\u0027 \u0027+key;}).sort().join(\u0027\n\u0027)) //jslint-quiet
|
|
773
985
|
case "keys":
|
|
774
986
|
script = (
|
|
775
|
-
"console.error(Object.keys(" + match2
|
|
776
|
-
").map(function(key){return("
|
|
777
|
-
"typeof " + match2 + "[key]===\u0027object\u0027&&"
|
|
778
|
-
match2 + "[key]&&"
|
|
779
|
-
match2 + "[key]===global[key]"
|
|
780
|
-
"?\u0027global\u0027"
|
|
781
|
-
":typeof " + match2 + "[key]"
|
|
782
|
-
")+\u0027 \u0027+key;"
|
|
783
|
-
"}).sort().join(\u0027\\n\u0027))\n"
|
|
987
|
+
"console.error(Object.keys(" + match2
|
|
988
|
+
+ ").map(function(key){return("
|
|
989
|
+
+ "typeof " + match2 + "[key]===\u0027object\u0027&&"
|
|
990
|
+
+ match2 + "[key]&&"
|
|
991
|
+
+ match2 + "[key]===global[key]"
|
|
992
|
+
+ "?\u0027global\u0027"
|
|
993
|
+
+ ":typeof " + match2 + "[key]"
|
|
994
|
+
+ ")+\u0027 \u0027+key;"
|
|
995
|
+
+ "}).sort().join(\u0027\\n\u0027))\n"
|
|
784
996
|
);
|
|
785
997
|
break;
|
|
786
998
|
// syntax-sugar - print String(val)
|
|
@@ -794,9 +1006,9 @@ import moduleUrl from "url";
|
|
|
794
1006
|
};
|
|
795
1007
|
}());
|
|
796
1008
|
(function watchDir() {
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
1009
|
+
|
|
1010
|
+
// this function will watch current-directory for changes
|
|
1011
|
+
|
|
800
1012
|
moduleFs.readdir(".", function (ignore, fileList) {
|
|
801
1013
|
fileList.forEach(function (file) {
|
|
802
1014
|
if (file[0] === ".") {
|
|
@@ -820,15 +1032,16 @@ import moduleUrl from "url";
|
|
|
820
1032
|
' "$@" # '
|
|
821
1033
|
)}
|
|
822
1034
|
|
|
823
|
-
|
|
824
|
-
# this function will create .png logo
|
|
1035
|
+
shImageLogoCreate() {(set -e
|
|
1036
|
+
# this function will create .png logo
|
|
1037
|
+
local SIZE
|
|
825
1038
|
echo '
|
|
826
1039
|
<!DOCTYPE html>
|
|
827
1040
|
<html lang="en">
|
|
828
1041
|
<head>
|
|
829
1042
|
<title>logo</title>
|
|
830
1043
|
<style>
|
|
831
|
-
/* sh jslint_ci.sh shBrowserScreenshot
|
|
1044
|
+
/* sh jslint_ci.sh shBrowserScreenshot asset_image_logo.html --window-size=512x512 */
|
|
832
1045
|
/* csslint box-model:false */
|
|
833
1046
|
/* csslint ignore:start */
|
|
834
1047
|
*,
|
|
@@ -839,7 +1052,7 @@ shImageJslintCreate() {(set -e
|
|
|
839
1052
|
@font-face {
|
|
840
1053
|
font-family: Daley;
|
|
841
1054
|
font-weight: bold;
|
|
842
|
-
src: url("
|
|
1055
|
+
src: url("asset_font_daley_bold.woff2") format("woff2");
|
|
843
1056
|
}
|
|
844
1057
|
/* csslint ignore:end */
|
|
845
1058
|
body,
|
|
@@ -884,26 +1097,26 @@ div {
|
|
|
884
1097
|
</div>
|
|
885
1098
|
</body>
|
|
886
1099
|
</html>
|
|
887
|
-
' > .
|
|
888
|
-
cp
|
|
889
|
-
# screenshot
|
|
890
|
-
shBrowserScreenshot .
|
|
1100
|
+
' > .artifact/asset_image_logo_512.html
|
|
1101
|
+
cp asset_font_daley_bold.woff2 .artifact || true
|
|
1102
|
+
# screenshot asset_image_logo_512.png
|
|
1103
|
+
shBrowserScreenshot .artifact/asset_image_logo_512.html \
|
|
891
1104
|
--window-size=512x512 \
|
|
892
|
-
-screenshot=.
|
|
1105
|
+
-screenshot=.artifact/asset_image_logo_512.png
|
|
893
1106
|
# create various smaller thumbnails
|
|
894
1107
|
for SIZE in 32 64 128 256
|
|
895
1108
|
do
|
|
896
|
-
convert -resize "${SIZE}x${SIZE}" .
|
|
897
|
-
".
|
|
1109
|
+
convert -resize "${SIZE}x${SIZE}" .artifact/asset_image_logo_512.png \
|
|
1110
|
+
".artifact/asset_image_logo_$SIZE.png"
|
|
898
1111
|
printf \
|
|
899
|
-
"
|
|
1112
|
+
"shImageLogoCreate - wrote - .artifact/asset_image_logo_$SIZE.png\n" 1>&2
|
|
900
1113
|
done
|
|
901
1114
|
# convert to svg @ https://convertio.co/png-svg/
|
|
902
1115
|
)}
|
|
903
1116
|
|
|
904
1117
|
shImageToDataUri() {(set -e
|
|
905
1118
|
# this function will convert image $1 to data-uri string
|
|
906
|
-
node --input-type=module
|
|
1119
|
+
node --input-type=module --eval '
|
|
907
1120
|
import moduleFs from "fs";
|
|
908
1121
|
import moduleHttps from "https";
|
|
909
1122
|
(async function () {
|
|
@@ -944,45 +1157,45 @@ shJsonNormalize() {(set -e
|
|
|
944
1157
|
# 1. read json-data from file $1
|
|
945
1158
|
# 2. normalize json-data
|
|
946
1159
|
# 3. write normalized json-data back to file $1
|
|
947
|
-
node --input-type=module
|
|
1160
|
+
node --input-type=module --eval '
|
|
948
1161
|
import moduleFs from "fs";
|
|
949
|
-
|
|
950
|
-
function identity(val) {
|
|
1162
|
+
function noop(val) {
|
|
951
1163
|
|
|
952
|
-
// This function will return <val>.
|
|
1164
|
+
// This function will do nothing except return <val>.
|
|
953
1165
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1166
|
+
return val;
|
|
1167
|
+
}
|
|
1168
|
+
function objectDeepCopyWithKeysSorted(obj) {
|
|
957
1169
|
|
|
958
|
-
//
|
|
1170
|
+
// This function will recursively deep-copy <obj> with keys sorted.
|
|
959
1171
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1172
|
+
let sorted;
|
|
1173
|
+
if (typeof obj !== "object" || !obj) {
|
|
1174
|
+
return obj;
|
|
1175
|
+
}
|
|
964
1176
|
|
|
965
|
-
//
|
|
1177
|
+
// Recursively deep-copy list with child-keys sorted.
|
|
966
1178
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1179
|
+
if (Array.isArray(obj)) {
|
|
1180
|
+
return obj.map(objectDeepCopyWithKeysSorted);
|
|
1181
|
+
}
|
|
970
1182
|
|
|
971
|
-
//
|
|
1183
|
+
// Recursively deep-copy obj with keys sorted.
|
|
972
1184
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1185
|
+
sorted = {};
|
|
1186
|
+
Object.keys(obj).sort().forEach(function (key) {
|
|
1187
|
+
sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
|
|
1188
|
+
});
|
|
1189
|
+
return sorted;
|
|
1190
|
+
}
|
|
1191
|
+
(async function () {
|
|
979
1192
|
console.error("shJsonNormalize - " + process.argv[1]);
|
|
980
|
-
moduleFs.promises.writeFile(
|
|
1193
|
+
await moduleFs.promises.writeFile(
|
|
981
1194
|
process.argv[1],
|
|
982
1195
|
JSON.stringify(
|
|
983
1196
|
objectDeepCopyWithKeysSorted(
|
|
984
1197
|
JSON.parse(
|
|
985
|
-
|
|
1198
|
+
noop(
|
|
986
1199
|
await moduleFs.promises.readFile(
|
|
987
1200
|
process.argv[1],
|
|
988
1201
|
"utf8"
|
|
@@ -993,16 +1206,26 @@ import moduleFs from "fs";
|
|
|
993
1206
|
)
|
|
994
1207
|
),
|
|
995
1208
|
undefined,
|
|
996
|
-
4
|
|
1209
|
+
Number(process.argv[2]) || 4
|
|
997
1210
|
) + "\n"
|
|
998
1211
|
);
|
|
999
1212
|
}());
|
|
1000
1213
|
' "$@" # '
|
|
1001
1214
|
)}
|
|
1002
1215
|
|
|
1216
|
+
shNpmPublishV0() {(set -e
|
|
1217
|
+
# this function will npm-publish name $1 with bare package.json
|
|
1218
|
+
local DIR
|
|
1219
|
+
DIR=/tmp/shNpmPublishV0
|
|
1220
|
+
rm -rf "$DIR" && mkdir -p "$DIR" && cd "$DIR"
|
|
1221
|
+
printf "{\"name\":\"$1\",\"version\":\"0.0.1\"}\n" > package.json
|
|
1222
|
+
shift
|
|
1223
|
+
npm publish "$@"
|
|
1224
|
+
)}
|
|
1225
|
+
|
|
1003
1226
|
shRawLibFetch() {(set -e
|
|
1004
1227
|
# this function will fetch raw-lib from $1
|
|
1005
|
-
node --input-type=module
|
|
1228
|
+
node --input-type=module --eval '
|
|
1006
1229
|
import moduleChildProcess from "child_process";
|
|
1007
1230
|
import moduleFs from "fs";
|
|
1008
1231
|
import moduleHttps from "https";
|
|
@@ -1129,12 +1352,12 @@ import modulePath from "path";
|
|
|
1129
1352
|
}
|
|
1130
1353
|
if (elem.dateCommitted) {
|
|
1131
1354
|
result += (
|
|
1132
|
-
"\n\n\n/*\n"
|
|
1133
|
-
"repo " + elem.prefix.replace("/blob/", "/tree/") + "\n"
|
|
1134
|
-
"committed " + (
|
|
1135
|
-
/\b\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\b
|
|
1136
|
-
).exec(elem.dateCommitted.toString())[0] + "\n"
|
|
1137
|
-
"*/"
|
|
1355
|
+
"\n\n\n/*\n"
|
|
1356
|
+
+ "repo " + elem.prefix.replace("/blob/", "/tree/") + "\n"
|
|
1357
|
+
+ "committed " + (
|
|
1358
|
+
/\b\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\b|$/
|
|
1359
|
+
).exec(elem.dateCommitted.toString())[0] + "\n"
|
|
1360
|
+
+ "*/"
|
|
1138
1361
|
);
|
|
1139
1362
|
}
|
|
1140
1363
|
// comment /*...*/
|
|
@@ -1145,15 +1368,17 @@ import modulePath from "path";
|
|
|
1145
1368
|
/\*\//g
|
|
1146
1369
|
), "*\\/") + "\n*/";
|
|
1147
1370
|
}
|
|
1148
|
-
//
|
|
1371
|
+
// init header and footer
|
|
1149
1372
|
result += (
|
|
1150
|
-
"\n\n\n/*\nfile " + elem.url + "\n*/\n"
|
|
1151
|
-
elem.
|
|
1373
|
+
"\n\n\n/*\nfile " + elem.url + "\n*/\n"
|
|
1374
|
+
+ (elem.header || "")
|
|
1375
|
+
+ elem.data.toString().trim()
|
|
1376
|
+
+ (elem.footer || "")
|
|
1152
1377
|
);
|
|
1153
1378
|
});
|
|
1154
1379
|
result = (
|
|
1155
|
-
"\n" + result.trim()
|
|
1156
|
-
"\n\n\n/*\nfile none\n*/\n/*jslint-enable*/\n"
|
|
1380
|
+
"\n" + result.trim()
|
|
1381
|
+
+ "\n\n\n/*\nfile none\n*/\n/*jslint-enable*/\n"
|
|
1157
1382
|
);
|
|
1158
1383
|
// comment #!
|
|
1159
1384
|
result = result.replace((
|
|
@@ -1165,11 +1390,11 @@ import modulePath from "path";
|
|
|
1165
1390
|
), "\n");
|
|
1166
1391
|
// remove trailing-whitespace
|
|
1167
1392
|
result = result.replace((
|
|
1168
|
-
/[\t
|
|
1393
|
+
/[\t ]+$/gm
|
|
1169
1394
|
), "");
|
|
1170
1395
|
// remove leading-newline before ket
|
|
1171
1396
|
result = result.replace((
|
|
1172
|
-
/\n+?(\n
|
|
1397
|
+
/\n+?(\n *?\})/g
|
|
1173
1398
|
), "$1");
|
|
1174
1399
|
// eslint - no-multiple-empty-lines
|
|
1175
1400
|
// https://github.com/eslint/eslint/blob/v7.2.0/docs/rules/no-multiple-empty-lines.md //jslint-quiet
|
|
@@ -1186,17 +1411,17 @@ import modulePath from "path";
|
|
|
1186
1411
|
result = result.replace(new RegExp(aa, flags), bb);
|
|
1187
1412
|
if (result0 === result) {
|
|
1188
1413
|
throw new Error(
|
|
1189
|
-
"shRawLibFetch - cannot find-and-replace snippet "
|
|
1190
|
-
JSON.stringify(aa)
|
|
1414
|
+
"shRawLibFetch - cannot find-and-replace snippet "
|
|
1415
|
+
+ JSON.stringify(aa)
|
|
1191
1416
|
);
|
|
1192
1417
|
}
|
|
1193
1418
|
});
|
|
1194
1419
|
// init header
|
|
1195
1420
|
header = (
|
|
1196
|
-
matchObj.input.slice(0, matchObj.index)
|
|
1197
|
-
"/*jslint-disable*/\n/*\nshRawLibFetch\n"
|
|
1198
|
-
JSON.stringify(JSON.parse(matchObj[1]), undefined, 4) + "\n"
|
|
1199
|
-
matchObj[2].split("\n\n").filter(function (elem) {
|
|
1421
|
+
matchObj.input.slice(0, matchObj.index)
|
|
1422
|
+
+ "/*jslint-disable*/\n/*\nshRawLibFetch\n"
|
|
1423
|
+
+ JSON.stringify(JSON.parse(matchObj[1]), undefined, 4) + "\n"
|
|
1424
|
+
+ matchObj[2].split("\n\n").filter(function (elem) {
|
|
1200
1425
|
return elem.trim();
|
|
1201
1426
|
}).map(function (elem) {
|
|
1202
1427
|
return elem.trim().replace((
|
|
@@ -1231,8 +1456,8 @@ import modulePath from "path";
|
|
|
1231
1456
|
});
|
|
1232
1457
|
if (result0 === result) {
|
|
1233
1458
|
throw new Error(
|
|
1234
|
-
"shRawLibFetch - cannot find-and-replace snippet "
|
|
1235
|
-
JSON.stringify(aa)
|
|
1459
|
+
"shRawLibFetch - cannot find-and-replace snippet "
|
|
1460
|
+
+ JSON.stringify(aa)
|
|
1236
1461
|
);
|
|
1237
1462
|
}
|
|
1238
1463
|
return "";
|
|
@@ -1247,8 +1472,8 @@ import modulePath from "path";
|
|
|
1247
1472
|
return;
|
|
1248
1473
|
}
|
|
1249
1474
|
data = (
|
|
1250
|
-
"data:" + dataUriType + ";base64,"
|
|
1251
|
-
data.toString("base64")
|
|
1475
|
+
"data:" + dataUriType + ";base64,"
|
|
1476
|
+
+ data.toString("base64")
|
|
1252
1477
|
);
|
|
1253
1478
|
result0 = result;
|
|
1254
1479
|
result = result.replace(
|
|
@@ -1260,15 +1485,15 @@ import modulePath from "path";
|
|
|
1260
1485
|
);
|
|
1261
1486
|
if (result0 === result) {
|
|
1262
1487
|
throw new Error(
|
|
1263
|
-
"shRawLibFetch - cannot find-and-replace snippet "
|
|
1264
|
-
JSON.stringify(exports)
|
|
1488
|
+
"shRawLibFetch - cannot find-and-replace snippet "
|
|
1489
|
+
+ JSON.stringify(exports)
|
|
1265
1490
|
);
|
|
1266
1491
|
}
|
|
1267
1492
|
});
|
|
1268
1493
|
// init footer
|
|
1269
1494
|
result = header + result;
|
|
1270
1495
|
matchObj.input.replace((
|
|
1271
|
-
/\n\/\*\nfile\
|
|
1496
|
+
/\n\/\*\nfile none\n\*\/\n\/\*jslint-enable\*\/\n([\S\s]+)/
|
|
1272
1497
|
), function (ignore, match1) {
|
|
1273
1498
|
result += "\n\n" + match1.trim() + "\n";
|
|
1274
1499
|
});
|
|
@@ -1277,579 +1502,1160 @@ import modulePath from "path";
|
|
|
1277
1502
|
});
|
|
1278
1503
|
}());
|
|
1279
1504
|
' "$@" # '
|
|
1280
|
-
git diff
|
|
1505
|
+
git diff
|
|
1506
|
+
)}
|
|
1507
|
+
|
|
1508
|
+
shRmDsStore() {(set -e
|
|
1509
|
+
# this function will recursively rm .DS_Store from current-dir
|
|
1510
|
+
# http://stackoverflow.com/questions/2016844/bash-recursively-remove-files
|
|
1511
|
+
local NAME
|
|
1512
|
+
for NAME in "._*" ".DS_Store" "desktop.ini" "npm-debug.log" "*~"
|
|
1513
|
+
do
|
|
1514
|
+
find . -iname "$NAME" -print0 | xargs -0 rm -f || true
|
|
1515
|
+
done
|
|
1281
1516
|
)}
|
|
1282
1517
|
|
|
1283
1518
|
shRunWithCoverage() {(set -e
|
|
1284
1519
|
# this function will run nodejs command $@ with v8-coverage
|
|
1285
|
-
# and create coverage-report .
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1520
|
+
# and create coverage-report .artifact/coverage/index.html
|
|
1521
|
+
node --input-type=module --eval '
|
|
1522
|
+
/*jslint indent2*/
|
|
1523
|
+
let moduleChildProcess;
|
|
1524
|
+
let moduleFs;
|
|
1525
|
+
let moduleFsInitResolveList;
|
|
1526
|
+
let modulePath;
|
|
1527
|
+
let moduleUrl;
|
|
1528
|
+
function assertOrThrow(condition, message) {
|
|
1529
|
+
if (!condition) {
|
|
1530
|
+
throw (
|
|
1531
|
+
(!message || typeof message === "string")
|
|
1532
|
+
? new Error(String(message).slice(0, 2048))
|
|
1533
|
+
: message
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
async function fsWriteFileWithParents(pathname, data) {
|
|
1538
|
+
await moduleFsInit();
|
|
1539
|
+
try {
|
|
1540
|
+
await moduleFs.promises.writeFile(pathname, data);
|
|
1541
|
+
} catch (ignore) {
|
|
1542
|
+
await moduleFs.promises.mkdir(modulePath.dirname(pathname), {
|
|
1543
|
+
recursive: true
|
|
1544
|
+
});
|
|
1545
|
+
await moduleFs.promises.writeFile(pathname, data);
|
|
1546
|
+
}
|
|
1547
|
+
console.error("wrote file " + pathname);
|
|
1548
|
+
}
|
|
1549
|
+
function htmlEscape(str) {
|
|
1550
|
+
return String(str).replace((
|
|
1551
|
+
/&/g
|
|
1552
|
+
), "&").replace((
|
|
1553
|
+
/</g
|
|
1554
|
+
), "<").replace((
|
|
1555
|
+
/>/g
|
|
1556
|
+
), ">");
|
|
1557
|
+
}
|
|
1558
|
+
async function moduleFsInit() {
|
|
1303
1559
|
|
|
1304
|
-
|
|
1560
|
+
if (moduleFs !== undefined) {
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (moduleFsInitResolveList !== undefined) {
|
|
1564
|
+
return new Promise(function (resolve) {
|
|
1565
|
+
moduleFsInitResolveList.push(resolve);
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
moduleFsInitResolveList = [];
|
|
1569
|
+
[
|
|
1570
|
+
moduleChildProcess,
|
|
1571
|
+
moduleFs,
|
|
1572
|
+
modulePath,
|
|
1573
|
+
moduleUrl
|
|
1574
|
+
] = await Promise.all([
|
|
1575
|
+
import("child_process"),
|
|
1576
|
+
import("fs"),
|
|
1577
|
+
import("path"),
|
|
1578
|
+
import("url")
|
|
1579
|
+
]);
|
|
1580
|
+
while (moduleFsInitResolveList.length > 0) {
|
|
1581
|
+
moduleFsInitResolveList.shift()();
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
function v8CoverageListMerge(processCovs) {
|
|
1585
|
+
let resultMerged = []; // List of merged scripts from processCovs.
|
|
1586
|
+
let urlToScriptDict = new Map(); // Map scriptCov.url to scriptCovs.
|
|
1305
1587
|
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1588
|
+
function compareRangeList(aa, bb) {
|
|
1589
|
+
if (aa.startOffset !== bb.startOffset) {
|
|
1590
|
+
return aa.startOffset - bb.startOffset;
|
|
1591
|
+
}
|
|
1592
|
+
return bb.endOffset - aa.endOffset;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
function dictKeyValueAppend(dict, key, val) {
|
|
1596
|
+
let list = dict.get(key);
|
|
1597
|
+
if (list === undefined) {
|
|
1598
|
+
list = [];
|
|
1599
|
+
dict.set(key, list);
|
|
1600
|
+
}
|
|
1601
|
+
list.push(val);
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
function mergeTreeList(parentTrees) {
|
|
1605
|
+
if (parentTrees.length <= 1) {
|
|
1606
|
+
return parentTrees[0];
|
|
1607
|
+
}
|
|
1608
|
+
return {
|
|
1609
|
+
children: mergeTreeListToChildren(parentTrees),
|
|
1610
|
+
delta: parentTrees.reduce(function (aa, bb) {
|
|
1611
|
+
return aa + bb.delta;
|
|
1612
|
+
}, 0),
|
|
1613
|
+
end: parentTrees[0].end,
|
|
1614
|
+
start: parentTrees[0].start
|
|
1310
1615
|
};
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
let
|
|
1315
|
-
let
|
|
1316
|
-
let
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
function mergeTreeListToChildren(parentTrees) {
|
|
1619
|
+
let openRange;
|
|
1620
|
+
let parentToChildDict = new Map(); // Map parent to child.
|
|
1621
|
+
let queueList;
|
|
1622
|
+
let queueListIi = 0;
|
|
1623
|
+
let queueOffset;
|
|
1624
|
+
let queueTrees;
|
|
1625
|
+
let resultChildren = [];
|
|
1626
|
+
let startToTreeDict = new Map(); // Map tree.start to tree.
|
|
1627
|
+
function nextXxx() {
|
|
1628
|
+
let [
|
|
1629
|
+
nextOffset, nextTrees
|
|
1630
|
+
] = queueList[queueListIi] || [];
|
|
1631
|
+
let openRangeEnd;
|
|
1632
|
+
if (queueTrees === undefined) {
|
|
1633
|
+
queueListIi += 1;
|
|
1634
|
+
} else if (nextOffset === undefined || nextOffset > queueOffset) {
|
|
1635
|
+
nextOffset = queueOffset;
|
|
1636
|
+
nextTrees = queueTrees;
|
|
1637
|
+
queueTrees = undefined;
|
|
1638
|
+
} else {
|
|
1639
|
+
if (nextOffset === queueOffset) {
|
|
1640
|
+
queueTrees.forEach(function (tree) {
|
|
1641
|
+
nextTrees.push(tree);
|
|
1642
|
+
});
|
|
1643
|
+
queueTrees = undefined;
|
|
1644
|
+
}
|
|
1645
|
+
queueListIi += 1;
|
|
1646
|
+
}
|
|
1647
|
+
if (nextOffset === undefined) {
|
|
1648
|
+
if (openRange !== undefined) {
|
|
1649
|
+
resultAppendNextChild();
|
|
1650
|
+
}
|
|
1651
|
+
return true;
|
|
1652
|
+
}
|
|
1653
|
+
if (openRange !== undefined && openRange.end <= nextOffset) {
|
|
1654
|
+
resultAppendNextChild();
|
|
1655
|
+
openRange = undefined;
|
|
1656
|
+
}
|
|
1657
|
+
if (openRange === undefined) {
|
|
1658
|
+
openRangeEnd = nextOffset + 1;
|
|
1659
|
+
nextTrees.forEach(function ({
|
|
1660
|
+
parentIi,
|
|
1661
|
+
tree
|
|
1662
|
+
}) {
|
|
1663
|
+
openRangeEnd = Math.max(openRangeEnd, tree.end);
|
|
1664
|
+
dictKeyValueAppend(parentToChildDict, parentIi, tree);
|
|
1665
|
+
});
|
|
1666
|
+
queueOffset = openRangeEnd;
|
|
1667
|
+
openRange = {
|
|
1668
|
+
end: openRangeEnd,
|
|
1669
|
+
start: nextOffset
|
|
1670
|
+
};
|
|
1671
|
+
} else {
|
|
1672
|
+
nextTrees.forEach(function ({
|
|
1673
|
+
parentIi,
|
|
1674
|
+
tree
|
|
1675
|
+
}) {
|
|
1676
|
+
let right;
|
|
1677
|
+
if (tree.end > openRange.end) {
|
|
1678
|
+
right = treeSplit(tree, openRange.end);
|
|
1679
|
+
if (queueTrees === undefined) {
|
|
1680
|
+
queueTrees = [];
|
|
1681
|
+
}
|
|
1682
|
+
queueTrees.push({
|
|
1683
|
+
parentIi,
|
|
1684
|
+
tree: right
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1687
|
+
dictKeyValueAppend(parentToChildDict, parentIi, tree);
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
function resultAppendNextChild() {
|
|
1692
|
+
let treesMatching = [];
|
|
1693
|
+
parentToChildDict.forEach(function (nested) {
|
|
1694
|
+
if (
|
|
1695
|
+
nested.length === 1
|
|
1696
|
+
&& nested[0].start === openRange.start
|
|
1697
|
+
&& nested[0].end === openRange.end
|
|
1698
|
+
) {
|
|
1699
|
+
treesMatching.push(nested[0]);
|
|
1700
|
+
} else {
|
|
1701
|
+
treesMatching.push({
|
|
1702
|
+
children: nested,
|
|
1703
|
+
delta: 0,
|
|
1704
|
+
end: openRange.end,
|
|
1705
|
+
start: openRange.start
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
});
|
|
1709
|
+
parentToChildDict.clear();
|
|
1710
|
+
resultChildren.push(mergeTreeList(treesMatching));
|
|
1711
|
+
}
|
|
1712
|
+
function treeSplit(tree, offset) {
|
|
1713
|
+
let child;
|
|
1714
|
+
let ii = 0;
|
|
1715
|
+
let leftChildLen = tree.children.length;
|
|
1716
|
+
let mid;
|
|
1717
|
+
let resultTree;
|
|
1718
|
+
let rightChildren;
|
|
1719
|
+
while (ii < tree.children.length) {
|
|
1720
|
+
child = tree.children[ii];
|
|
1721
|
+
if (child.start < offset && offset < child.end) {
|
|
1722
|
+
mid = treeSplit(child, offset);
|
|
1723
|
+
leftChildLen = ii + 1;
|
|
1724
|
+
break;
|
|
1725
|
+
}
|
|
1726
|
+
if (child.start >= offset) {
|
|
1727
|
+
leftChildLen = ii;
|
|
1728
|
+
break;
|
|
1729
|
+
}
|
|
1730
|
+
ii += 1;
|
|
1731
|
+
}
|
|
1732
|
+
rightChildren = tree.children.splice(
|
|
1733
|
+
leftChildLen,
|
|
1734
|
+
tree.children.length - leftChildLen
|
|
1735
|
+
);
|
|
1736
|
+
if (mid !== undefined) {
|
|
1737
|
+
rightChildren.unshift(mid);
|
|
1738
|
+
}
|
|
1739
|
+
resultTree = {
|
|
1740
|
+
children: rightChildren,
|
|
1741
|
+
delta: tree.delta,
|
|
1742
|
+
end: tree.end,
|
|
1743
|
+
start: offset
|
|
1744
|
+
};
|
|
1745
|
+
tree.end = offset;
|
|
1746
|
+
return resultTree;
|
|
1747
|
+
}
|
|
1748
|
+
parentTrees.forEach(function (parentTree, parentIi) {
|
|
1749
|
+
parentTree.children.forEach(function (child) {
|
|
1750
|
+
dictKeyValueAppend(startToTreeDict, child.start, {
|
|
1751
|
+
parentIi,
|
|
1752
|
+
tree: child
|
|
1753
|
+
});
|
|
1754
|
+
});
|
|
1755
|
+
});
|
|
1756
|
+
queueList = Array.from(startToTreeDict).map(function ([
|
|
1757
|
+
startOffset, trees
|
|
1758
|
+
]) {
|
|
1759
|
+
return [
|
|
1760
|
+
startOffset, trees
|
|
1761
|
+
];
|
|
1762
|
+
}).sort(function (aa, bb) {
|
|
1763
|
+
return aa[0] - bb[0];
|
|
1764
|
+
});
|
|
1765
|
+
while (true) {
|
|
1766
|
+
if (nextXxx()) {
|
|
1767
|
+
break;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
return resultChildren;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
function sortFunc(funcCov) {
|
|
1774
|
+
funcCov.ranges = treeToRanges(treeFromSortedRanges(
|
|
1775
|
+
funcCov.ranges.sort(compareRangeList)
|
|
1776
|
+
));
|
|
1777
|
+
return funcCov;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
function sortScript(scriptCov) {
|
|
1781
|
+
|
|
1782
|
+
scriptCov.functions.forEach(function (funcCov) {
|
|
1783
|
+
sortFunc(funcCov);
|
|
1784
|
+
});
|
|
1785
|
+
scriptCov.functions.sort(function (aa, bb) {
|
|
1786
|
+
return compareRangeList(aa.ranges[0], bb.ranges[0]);
|
|
1787
|
+
});
|
|
1788
|
+
return scriptCov;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
function treeFromSortedRanges(ranges) {
|
|
1792
|
+
let root;
|
|
1793
|
+
let stack = []; // Stack of parent trees and parent counts.
|
|
1794
|
+
ranges.forEach(function (range) {
|
|
1795
|
+
let node = {
|
|
1796
|
+
children: [],
|
|
1797
|
+
delta: range.count,
|
|
1798
|
+
end: range.endOffset,
|
|
1799
|
+
start: range.startOffset
|
|
1800
|
+
};
|
|
1801
|
+
let parent;
|
|
1802
|
+
let parentCount;
|
|
1803
|
+
if (root === undefined) {
|
|
1804
|
+
root = node;
|
|
1805
|
+
stack.push([
|
|
1806
|
+
node, range.count
|
|
1807
|
+
]);
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
while (true) {
|
|
1811
|
+
[
|
|
1812
|
+
parent, parentCount
|
|
1813
|
+
] = stack[stack.length - 1];
|
|
1814
|
+
if (range.startOffset < parent.end) {
|
|
1815
|
+
break;
|
|
1816
|
+
}
|
|
1817
|
+
stack.pop();
|
|
1818
|
+
}
|
|
1819
|
+
node.delta -= parentCount;
|
|
1820
|
+
parent.children.push(node);
|
|
1821
|
+
stack.push([
|
|
1822
|
+
node, range.count
|
|
1823
|
+
]);
|
|
1824
|
+
});
|
|
1825
|
+
return root;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
function treeToRanges(tree) {
|
|
1829
|
+
let count;
|
|
1830
|
+
let cur;
|
|
1831
|
+
let ii;
|
|
1832
|
+
let parentCount;
|
|
1833
|
+
let ranges = [];
|
|
1834
|
+
let stack = [ // Stack of parent trees and counts.
|
|
1835
|
+
[
|
|
1836
|
+
tree, 0
|
|
1837
|
+
]
|
|
1838
|
+
];
|
|
1839
|
+
function normalizeRange(tree) {
|
|
1840
|
+
let children = [];
|
|
1841
|
+
let curEnd;
|
|
1842
|
+
let head;
|
|
1843
|
+
let tail = [];
|
|
1844
|
+
function endChain() {
|
|
1845
|
+
if (tail.length !== 0) {
|
|
1846
|
+
head.end = tail[tail.length - 1].end;
|
|
1847
|
+
tail.forEach(function (tailTree) {
|
|
1848
|
+
tailTree.children.forEach(function (subChild) {
|
|
1849
|
+
subChild.delta += tailTree.delta - head.delta;
|
|
1850
|
+
head.children.push(subChild);
|
|
1851
|
+
});
|
|
1852
|
+
});
|
|
1853
|
+
tail.length = 0;
|
|
1854
|
+
}
|
|
1855
|
+
normalizeRange(head);
|
|
1856
|
+
children.push(head);
|
|
1857
|
+
}
|
|
1858
|
+
tree.children.forEach(function (child) {
|
|
1859
|
+
if (head === undefined) {
|
|
1860
|
+
head = child;
|
|
1861
|
+
} else if (
|
|
1862
|
+
child.delta === head.delta && child.start === curEnd
|
|
1863
|
+
) {
|
|
1864
|
+
tail.push(child);
|
|
1865
|
+
} else {
|
|
1866
|
+
endChain();
|
|
1867
|
+
head = child;
|
|
1868
|
+
}
|
|
1869
|
+
curEnd = child.end;
|
|
1870
|
+
});
|
|
1871
|
+
if (head !== undefined) {
|
|
1872
|
+
endChain();
|
|
1873
|
+
}
|
|
1874
|
+
if (children.length === 1) {
|
|
1875
|
+
if (
|
|
1876
|
+
children[0].start === tree.start
|
|
1877
|
+
&& children[0].end === tree.end
|
|
1878
|
+
) {
|
|
1879
|
+
tree.delta += children[0].delta;
|
|
1880
|
+
tree.children = children[0].children;
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
tree.children = children;
|
|
1885
|
+
}
|
|
1886
|
+
normalizeRange(tree);
|
|
1887
|
+
while (stack.length > 0) {
|
|
1888
|
+
[
|
|
1889
|
+
cur, parentCount
|
|
1890
|
+
] = stack.pop();
|
|
1891
|
+
count = parentCount + cur.delta;
|
|
1892
|
+
ranges.push({
|
|
1893
|
+
count,
|
|
1894
|
+
endOffset: cur.end,
|
|
1895
|
+
startOffset: cur.start
|
|
1896
|
+
});
|
|
1897
|
+
ii = cur.children.length - 1;
|
|
1898
|
+
while (ii >= 0) {
|
|
1899
|
+
stack.push([
|
|
1900
|
+
cur.children[ii], count
|
|
1901
|
+
]);
|
|
1902
|
+
ii -= 1;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
return ranges;
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
if (processCovs.length === 0) {
|
|
1909
|
+
return {
|
|
1910
|
+
result: []
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
processCovs.forEach(function ({
|
|
1914
|
+
result
|
|
1915
|
+
}) {
|
|
1916
|
+
result.forEach(function (scriptCov) {
|
|
1917
|
+
dictKeyValueAppend(urlToScriptDict, scriptCov.url, scriptCov);
|
|
1918
|
+
});
|
|
1919
|
+
});
|
|
1920
|
+
urlToScriptDict.forEach(function (scriptCovs) {
|
|
1921
|
+
|
|
1922
|
+
let functions = [];
|
|
1923
|
+
let rangeToFuncDict = new Map();
|
|
1924
|
+
if (scriptCovs.length === 1) {
|
|
1925
|
+
resultMerged.push(sortScript(scriptCovs[0]));
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
scriptCovs.forEach(function ({
|
|
1929
|
+
functions
|
|
1321
1930
|
}) {
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1931
|
+
functions.forEach(function (funcCov) {
|
|
1932
|
+
dictKeyValueAppend(
|
|
1933
|
+
rangeToFuncDict,
|
|
1934
|
+
(
|
|
1935
|
+
funcCov.ranges[0].startOffset
|
|
1936
|
+
+ ";" + funcCov.ranges[0].endOffset
|
|
1937
|
+
),
|
|
1938
|
+
funcCov
|
|
1939
|
+
);
|
|
1940
|
+
});
|
|
1941
|
+
});
|
|
1942
|
+
rangeToFuncDict.forEach(function (funcCovs) {
|
|
1943
|
+
|
|
1944
|
+
let count = 0;
|
|
1945
|
+
let isBlockCoverage;
|
|
1946
|
+
let merged;
|
|
1947
|
+
let ranges;
|
|
1948
|
+
let trees = [];
|
|
1949
|
+
if (funcCovs.length === 1) {
|
|
1950
|
+
functions.push(sortFunc(funcCovs[0]));
|
|
1951
|
+
return;
|
|
1952
|
+
}
|
|
1953
|
+
funcCovs.forEach(function (funcCov) {
|
|
1954
|
+
count += (
|
|
1955
|
+
funcCov.count !== undefined
|
|
1956
|
+
? funcCov.count
|
|
1957
|
+
: funcCov.ranges[0].count
|
|
1958
|
+
);
|
|
1959
|
+
if (funcCov.isBlockCoverage) {
|
|
1960
|
+
trees.push(treeFromSortedRanges(funcCov.ranges));
|
|
1345
1961
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
1962
|
+
});
|
|
1963
|
+
if (trees.length > 0) {
|
|
1964
|
+
isBlockCoverage = true;
|
|
1965
|
+
ranges = treeToRanges(mergeTreeList(trees));
|
|
1966
|
+
} else {
|
|
1967
|
+
isBlockCoverage = false;
|
|
1968
|
+
ranges = [
|
|
1969
|
+
{
|
|
1970
|
+
count,
|
|
1971
|
+
endOffset: funcCovs[0].ranges[0].endOffset,
|
|
1972
|
+
startOffset: funcCovs[0].ranges[0].startOffset
|
|
1973
|
+
}
|
|
1974
|
+
];
|
|
1975
|
+
}
|
|
1976
|
+
merged = {
|
|
1977
|
+
functionName: funcCovs[0].functionName,
|
|
1978
|
+
isBlockCoverage,
|
|
1979
|
+
ranges
|
|
1980
|
+
};
|
|
1981
|
+
if (count !== ranges[0].count) {
|
|
1982
|
+
merged.count = count;
|
|
1983
|
+
}
|
|
1984
|
+
functions.push(merged);
|
|
1985
|
+
});
|
|
1986
|
+
resultMerged.push(sortScript({
|
|
1987
|
+
functions,
|
|
1988
|
+
scriptId: scriptCovs[0].scriptId,
|
|
1989
|
+
url: scriptCovs[0].url
|
|
1990
|
+
}));
|
|
1991
|
+
});
|
|
1992
|
+
Object.entries(resultMerged.sort(function (aa, bb) {
|
|
1993
|
+
return (
|
|
1994
|
+
aa.url > bb.url
|
|
1995
|
+
? 1
|
|
1996
|
+
: -1
|
|
1997
|
+
);
|
|
1998
|
+
})).forEach(function ([
|
|
1999
|
+
scriptId, scriptCov
|
|
2000
|
+
]) {
|
|
2001
|
+
scriptCov.scriptId = scriptId.toString(10);
|
|
2002
|
+
});
|
|
2003
|
+
return {
|
|
2004
|
+
result: resultMerged
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
async function v8CoverageReportCreate({
|
|
2008
|
+
consoleError,
|
|
2009
|
+
coverageDir,
|
|
2010
|
+
processArgv = []
|
|
2011
|
+
}) {
|
|
2012
|
+
let cwd;
|
|
2013
|
+
let exitCode = 0;
|
|
2014
|
+
let fileDict;
|
|
2015
|
+
let fileExcludeList = [];
|
|
2016
|
+
let fileIncludeList = [];
|
|
2017
|
+
let fileIncludeNodeModules;
|
|
2018
|
+
let processArgElem;
|
|
2019
|
+
let promiseList = [];
|
|
2020
|
+
let v8CoverageObj;
|
|
2021
|
+
|
|
2022
|
+
function htmlRender({
|
|
2023
|
+
fileList,
|
|
2024
|
+
lineList,
|
|
2025
|
+
modeIndex,
|
|
2026
|
+
pathname
|
|
2027
|
+
}) {
|
|
2028
|
+
let html;
|
|
2029
|
+
let padLines;
|
|
2030
|
+
let padPathname;
|
|
2031
|
+
let txt;
|
|
2032
|
+
let txtBorder;
|
|
2033
|
+
html = "";
|
|
2034
|
+
html += String(`
|
|
2035
|
+
<!DOCTYPE html>
|
|
1348
2036
|
<html lang="en">
|
|
1349
2037
|
<head>
|
|
1350
|
-
<title>
|
|
2038
|
+
<title>V8 Coverage Report</title>
|
|
1351
2039
|
<style>
|
|
1352
|
-
/*
|
|
2040
|
+
/* jslint utility2:true */
|
|
2041
|
+
/*csslint ignore:start*/
|
|
1353
2042
|
* {
|
|
1354
2043
|
box-sizing: border-box;
|
|
1355
|
-
|
|
2044
|
+
font-family: consolas, menlo, monospace;
|
|
1356
2045
|
}
|
|
1357
|
-
/*
|
|
2046
|
+
/*csslint ignore:end*/
|
|
2047
|
+
|
|
2048
|
+
/* css - coverage_report - general */
|
|
1358
2049
|
body {
|
|
1359
|
-
|
|
2050
|
+
margin: 0;
|
|
1360
2051
|
}
|
|
1361
2052
|
.coverage pre {
|
|
1362
|
-
|
|
2053
|
+
margin: 5px 0;
|
|
1363
2054
|
}
|
|
1364
2055
|
.coverage table {
|
|
1365
|
-
|
|
2056
|
+
border-collapse: collapse;
|
|
1366
2057
|
}
|
|
1367
2058
|
.coverage td,
|
|
1368
2059
|
.coverage th {
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
2060
|
+
border: 1px solid #777;
|
|
2061
|
+
line-height: 20px;
|
|
2062
|
+
margin: 0;
|
|
2063
|
+
padding: 5px 10px;
|
|
1372
2064
|
}
|
|
1373
2065
|
.coverage td span {
|
|
1374
|
-
|
|
1375
|
-
|
|
2066
|
+
display: inline-block;
|
|
2067
|
+
width: 100%;
|
|
1376
2068
|
}
|
|
1377
2069
|
.coverage .content {
|
|
1378
|
-
|
|
2070
|
+
padding: 0 5px;
|
|
1379
2071
|
}
|
|
1380
2072
|
.coverage .content a {
|
|
1381
|
-
|
|
2073
|
+
text-decoration: none;
|
|
1382
2074
|
}
|
|
1383
2075
|
.coverage .count {
|
|
1384
|
-
|
|
1385
|
-
|
|
2076
|
+
margin: 0 5px;
|
|
2077
|
+
padding: 0 5px;
|
|
1386
2078
|
}
|
|
1387
2079
|
.coverage .footer,
|
|
1388
2080
|
.coverage .header {
|
|
1389
|
-
|
|
2081
|
+
padding: 20px;
|
|
2082
|
+
}
|
|
2083
|
+
.coverage .footer {
|
|
2084
|
+
text-align: center;
|
|
1390
2085
|
}
|
|
1391
2086
|
.coverage .percentbar {
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
2087
|
+
height: 12px;
|
|
2088
|
+
margin: 2px 0;
|
|
2089
|
+
min-width: 200px;
|
|
2090
|
+
position: relative;
|
|
2091
|
+
width: 100%;
|
|
1397
2092
|
}
|
|
1398
2093
|
.coverage .percentbar div {
|
|
1399
|
-
|
|
1400
|
-
|
|
2094
|
+
height: 100%;
|
|
2095
|
+
position: absolute;
|
|
1401
2096
|
}
|
|
1402
2097
|
.coverage .title {
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
2098
|
+
font-size: large;
|
|
2099
|
+
font-weight: bold;
|
|
2100
|
+
margin-bottom: 10px;
|
|
1406
2101
|
}
|
|
1407
2102
|
|
|
2103
|
+
/* css - coverage_report - color */
|
|
1408
2104
|
.coverage td,
|
|
1409
2105
|
.coverage th {
|
|
1410
|
-
|
|
2106
|
+
background: #fff;
|
|
1411
2107
|
}
|
|
1412
|
-
.coverage .count
|
|
1413
|
-
|
|
1414
|
-
|
|
2108
|
+
.coverage .count,
|
|
2109
|
+
.coverage .coverageHigh {
|
|
2110
|
+
background: #9d9;
|
|
1415
2111
|
}
|
|
1416
|
-
.coverage .
|
|
1417
|
-
|
|
2112
|
+
.coverage .count {
|
|
2113
|
+
color: #666;
|
|
1418
2114
|
}
|
|
1419
|
-
.coverage .
|
|
1420
|
-
|
|
2115
|
+
.coverage .coverageIgnore {
|
|
2116
|
+
background: #ccc;
|
|
1421
2117
|
}
|
|
1422
|
-
.coverage .
|
|
1423
|
-
|
|
2118
|
+
.coverage .coverageLow,
|
|
2119
|
+
.coverage .uncovered {
|
|
2120
|
+
background: #ebb;
|
|
1424
2121
|
}
|
|
1425
|
-
.coverage .
|
|
1426
|
-
|
|
2122
|
+
.coverage .coverageMedium {
|
|
2123
|
+
background: #fd7;
|
|
1427
2124
|
}
|
|
2125
|
+
.coverage .footer,
|
|
2126
|
+
.coverage .header,
|
|
1428
2127
|
.coverage .lineno {
|
|
1429
|
-
|
|
2128
|
+
background: #ddd;
|
|
1430
2129
|
}
|
|
1431
2130
|
.coverage .percentbar {
|
|
1432
|
-
|
|
2131
|
+
background: #999;
|
|
1433
2132
|
}
|
|
1434
2133
|
.coverage .percentbar div {
|
|
1435
|
-
|
|
1436
|
-
}
|
|
1437
|
-
.coverage .uncovered {
|
|
1438
|
-
background: #dbb;
|
|
2134
|
+
background: #666;
|
|
1439
2135
|
}
|
|
1440
2136
|
|
|
2137
|
+
/* css - coverage_report - important */
|
|
1441
2138
|
.coverage pre:hover span,
|
|
1442
2139
|
.coverage tr:hover td {
|
|
1443
|
-
|
|
2140
|
+
background: #7d7;
|
|
1444
2141
|
}
|
|
1445
2142
|
.coverage pre:hover span.uncovered,
|
|
1446
2143
|
.coverage tr:hover td.coverageLow {
|
|
1447
|
-
|
|
2144
|
+
background: #f99;
|
|
1448
2145
|
}
|
|
1449
2146
|
</style>
|
|
1450
2147
|
</head>
|
|
1451
2148
|
<body class="coverage">
|
|
2149
|
+
<!-- header start -->
|
|
1452
2150
|
<div class="header">
|
|
1453
|
-
<div class="title">
|
|
2151
|
+
<div class="title">V8 Coverage Report</div>
|
|
1454
2152
|
<table>
|
|
1455
2153
|
<thead>
|
|
1456
|
-
<tr>
|
|
1457
|
-
<th>
|
|
1458
|
-
<th>
|
|
1459
|
-
</
|
|
2154
|
+
<tr>
|
|
2155
|
+
<th>Files covered</th>
|
|
2156
|
+
<th>Lines</th>
|
|
2157
|
+
<th>Remaining</th>
|
|
2158
|
+
</tr>
|
|
1460
2159
|
</thead>
|
|
1461
|
-
<tbody
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
);
|
|
1482
|
-
});
|
|
2160
|
+
<tbody>
|
|
2161
|
+
`).trim() + "\n";
|
|
2162
|
+
if (modeIndex) {
|
|
2163
|
+
padLines = String("(ignore) 100.00 %").length;
|
|
2164
|
+
padPathname = 32;
|
|
2165
|
+
fileList.unshift({
|
|
2166
|
+
linesCovered: 0,
|
|
2167
|
+
linesTotal: 0,
|
|
2168
|
+
modeCoverageIgnoreFile: "",
|
|
2169
|
+
pathname: "./"
|
|
2170
|
+
});
|
|
2171
|
+
fileList.slice(1).forEach(function ({
|
|
2172
|
+
linesCovered,
|
|
2173
|
+
linesTotal,
|
|
2174
|
+
modeCoverageIgnoreFile,
|
|
2175
|
+
pathname
|
|
2176
|
+
}) {
|
|
2177
|
+
if (!modeCoverageIgnoreFile) {
|
|
2178
|
+
fileList[0].linesCovered += linesCovered;
|
|
2179
|
+
fileList[0].linesTotal += linesTotal;
|
|
1483
2180
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
2181
|
+
padPathname = Math.max(padPathname, pathname.length + 2);
|
|
2182
|
+
padLines = Math.max(
|
|
2183
|
+
padLines,
|
|
2184
|
+
String(linesCovered + " / " + linesTotal).length
|
|
1487
2185
|
);
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
txtBorder = (
|
|
2189
|
+
"+" + "-".repeat(padPathname + 2) + "+"
|
|
2190
|
+
+ "-".repeat(padLines + 2) + "+\n"
|
|
2191
|
+
);
|
|
2192
|
+
txt = "";
|
|
2193
|
+
txt += "V8 Coverage Report\n";
|
|
2194
|
+
txt += txtBorder;
|
|
2195
|
+
txt += (
|
|
2196
|
+
"| " + String("Files covered").padEnd(padPathname, " ") + " | "
|
|
2197
|
+
+ String("Lines").padStart(padLines, " ") + " |\n"
|
|
2198
|
+
);
|
|
2199
|
+
txt += txtBorder;
|
|
2200
|
+
fileList.forEach(function ({
|
|
2201
|
+
linesCovered,
|
|
2202
|
+
linesTotal,
|
|
2203
|
+
modeCoverageIgnoreFile,
|
|
2204
|
+
pathname
|
|
2205
|
+
}, ii) {
|
|
2206
|
+
let coverageLevel;
|
|
2207
|
+
let coveragePct;
|
|
2208
|
+
let fill;
|
|
2209
|
+
let str1;
|
|
2210
|
+
let str2;
|
|
2211
|
+
let xx1;
|
|
2212
|
+
let xx2;
|
|
2213
|
+
coveragePct = Math.floor(10000 * linesCovered / linesTotal || 0);
|
|
2214
|
+
coverageLevel = (
|
|
2215
|
+
modeCoverageIgnoreFile
|
|
2216
|
+
? "coverageIgnore"
|
|
2217
|
+
: coveragePct >= 8000
|
|
2218
|
+
? "coverageHigh"
|
|
2219
|
+
: coveragePct >= 5000
|
|
2220
|
+
? "coverageMedium"
|
|
2221
|
+
: "coverageLow"
|
|
2222
|
+
);
|
|
2223
|
+
coveragePct = String(coveragePct).replace((
|
|
2224
|
+
/..$/m
|
|
2225
|
+
), ".$&");
|
|
2226
|
+
if (modeIndex && ii === 0) {
|
|
2227
|
+
fill = (
|
|
2228
|
+
"#" + Math.round(
|
|
2229
|
+
(100 - Number(coveragePct)) * 2.21
|
|
2230
|
+
).toString(16).padStart(2, "0")
|
|
2231
|
+
+ Math.round(
|
|
2232
|
+
Number(coveragePct) * 2.21
|
|
2233
|
+
).toString(16).padStart(2, "0")
|
|
2234
|
+
+ "00"
|
|
1494
2235
|
);
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
let coveragePct;
|
|
1503
|
-
let fill;
|
|
1504
|
-
let str1;
|
|
1505
|
-
let str2;
|
|
1506
|
-
let xx1;
|
|
1507
|
-
let xx2;
|
|
1508
|
-
coveragePct = Math.floor(10000 * linesCovered / linesTotal || 0);
|
|
1509
|
-
coverageLevel = (
|
|
1510
|
-
coveragePct >= 8000
|
|
1511
|
-
? "coverageHigh"
|
|
1512
|
-
: coveragePct >= 5000
|
|
1513
|
-
? "coverageMedium"
|
|
1514
|
-
: "coverageLow"
|
|
1515
|
-
);
|
|
1516
|
-
coveragePct = String(coveragePct).replace((
|
|
1517
|
-
/..$/m
|
|
1518
|
-
), ".$&");
|
|
1519
|
-
if (!lineList && ii === 0) {
|
|
1520
|
-
fill = (
|
|
1521
|
-
// red
|
|
1522
|
-
"#" + Math.round(
|
|
1523
|
-
(100 - Number(coveragePct)) * 2.21
|
|
1524
|
-
).toString(16).padStart(2, "0")
|
|
1525
|
-
// green
|
|
1526
|
-
+ Math.round(
|
|
1527
|
-
Number(coveragePct) * 2.21
|
|
1528
|
-
).toString(16).padStart(2, "0")
|
|
1529
|
-
+ // blue
|
|
1530
|
-
"00"
|
|
1531
|
-
);
|
|
1532
|
-
str1 = "coverage";
|
|
1533
|
-
str2 = coveragePct + " %";
|
|
1534
|
-
xx1 = 6 * str1.length + 20;
|
|
1535
|
-
xx2 = 6 * str2.length + 20;
|
|
1536
|
-
// fs - write coverage-badge.svg
|
|
1537
|
-
moduleFs.promises.writeFile((
|
|
1538
|
-
DIR_COVERAGE + "/coverage-badge.svg"
|
|
1539
|
-
), String(`
|
|
2236
|
+
str1 = "coverage";
|
|
2237
|
+
str2 = coveragePct + " %";
|
|
2238
|
+
xx1 = 6 * str1.length + 20;
|
|
2239
|
+
xx2 = 6 * str2.length + 20;
|
|
2240
|
+
promiseList.push(fsWriteFileWithParents((
|
|
2241
|
+
coverageDir + "coverage_badge.svg"
|
|
2242
|
+
), String(`
|
|
1540
2243
|
<svg height="20" width="${xx1 + xx2}" xmlns="http://www.w3.org/2000/svg">
|
|
1541
2244
|
<rect fill="#555" height="20" width="${xx1 + xx2}"/>
|
|
1542
2245
|
<rect fill="${fill}" height="20" width="${xx2}" x="${xx1}"/>
|
|
1543
2246
|
<g
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
2247
|
+
fill="#fff"
|
|
2248
|
+
font-family="verdana, geneva, dejavu sans, sans-serif"
|
|
2249
|
+
font-size="11"
|
|
2250
|
+
font-weight="bold"
|
|
2251
|
+
text-anchor="middle"
|
|
1549
2252
|
>
|
|
1550
2253
|
<text x="${0.5 * xx1}" y="14">${str1}</text>
|
|
1551
2254
|
<text x="${xx1 + 0.5 * xx2}" y="14">${str2}</text>
|
|
1552
2255
|
</g>
|
|
1553
2256
|
</svg>
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
2257
|
+
`).trim() + "\n"));
|
|
2258
|
+
pathname = "";
|
|
2259
|
+
}
|
|
2260
|
+
txt += (
|
|
2261
|
+
"| "
|
|
2262
|
+
+ String("./" + pathname).padEnd(padPathname, " ") + " | "
|
|
2263
|
+
+ String(
|
|
2264
|
+
modeCoverageIgnoreFile + " " + coveragePct + " %"
|
|
2265
|
+
).padStart(padLines, " ") + " |\n"
|
|
2266
|
+
);
|
|
2267
|
+
txt += (
|
|
2268
|
+
"| " + "*".repeat(
|
|
2269
|
+
Math.round(0.01 * coveragePct * padPathname)
|
|
2270
|
+
).padEnd(padPathname, "_") + " | "
|
|
2271
|
+
+ String(
|
|
2272
|
+
linesCovered + " / " + linesTotal
|
|
2273
|
+
).padStart(padLines, " ") + " |\n"
|
|
2274
|
+
);
|
|
2275
|
+
txt += txtBorder;
|
|
2276
|
+
pathname = htmlEscape(pathname);
|
|
2277
|
+
html += String(`
|
|
2278
|
+
<tr>
|
|
2279
|
+
<td class="${coverageLevel}">
|
|
2280
|
+
${(
|
|
2281
|
+
modeIndex
|
|
2282
|
+
? (
|
|
2283
|
+
"<a href=\"" + (pathname || "index") + ".html\">. / "
|
|
2284
|
+
+ pathname + "</a><br>"
|
|
2285
|
+
)
|
|
2286
|
+
: (
|
|
2287
|
+
"<a href=\""
|
|
2288
|
+
+ "../".repeat(pathname.split("/").length - 1)
|
|
2289
|
+
+ "index.html\">. / </a>"
|
|
2290
|
+
+ pathname + "<br>"
|
|
2291
|
+
)
|
|
2292
|
+
)}
|
|
2293
|
+
<div class="percentbar">
|
|
2294
|
+
<div style="width: ${coveragePct}%;"></div>
|
|
2295
|
+
</div>
|
|
2296
|
+
</td>
|
|
2297
|
+
<td style="text-align: right;">
|
|
2298
|
+
${modeCoverageIgnoreFile} ${coveragePct} %<br>
|
|
1591
2299
|
${linesCovered} / ${linesTotal}
|
|
1592
|
-
</td>
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
2300
|
+
</td>
|
|
2301
|
+
<td style="text-align: right;">
|
|
2302
|
+
<br>
|
|
2303
|
+
${linesTotal - linesCovered} / ${linesTotal}
|
|
2304
|
+
</td>
|
|
2305
|
+
</tr>
|
|
2306
|
+
`).trim() + "\n";
|
|
2307
|
+
});
|
|
2308
|
+
html += String(`
|
|
2309
|
+
</tbody>
|
|
1597
2310
|
</table>
|
|
1598
2311
|
</div>
|
|
2312
|
+
<!-- header end -->
|
|
2313
|
+
`).trim() + "\n";
|
|
2314
|
+
if (!modeIndex) {
|
|
2315
|
+
html += String(`
|
|
2316
|
+
<!-- content start -->
|
|
1599
2317
|
<div class="content">
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
2318
|
+
`).trim() + "\n";
|
|
2319
|
+
lineList.forEach(function ({
|
|
2320
|
+
count,
|
|
2321
|
+
holeList,
|
|
2322
|
+
line,
|
|
2323
|
+
startOffset
|
|
2324
|
+
}, ii) {
|
|
2325
|
+
let chunk;
|
|
2326
|
+
let inHole;
|
|
2327
|
+
let lineHtml;
|
|
2328
|
+
let lineId;
|
|
2329
|
+
lineHtml = "";
|
|
2330
|
+
lineId = "line_" + (ii + 1);
|
|
2331
|
+
switch (count) {
|
|
2332
|
+
case -1:
|
|
2333
|
+
case 0:
|
|
2334
|
+
if (holeList.length === 0) {
|
|
2335
|
+
lineHtml += "</span>";
|
|
2336
|
+
lineHtml += "<span class=\"uncovered\">";
|
|
2337
|
+
lineHtml += htmlEscape(line);
|
|
2338
|
+
break;
|
|
2339
|
+
}
|
|
2340
|
+
line = line.split("").map(function (char) {
|
|
2341
|
+
return {
|
|
2342
|
+
char,
|
|
2343
|
+
isHole: undefined
|
|
2344
|
+
};
|
|
2345
|
+
});
|
|
2346
|
+
holeList.forEach(function ([
|
|
2347
|
+
aa, bb
|
|
2348
|
+
]) {
|
|
2349
|
+
aa = Math.max(aa - startOffset, 0);
|
|
2350
|
+
bb = Math.min(bb - startOffset, line.length);
|
|
2351
|
+
while (aa < bb) {
|
|
2352
|
+
line[aa].isHole = true;
|
|
2353
|
+
aa += 1;
|
|
2354
|
+
}
|
|
2355
|
+
});
|
|
2356
|
+
chunk = "";
|
|
2357
|
+
line.forEach(function ({
|
|
2358
|
+
char,
|
|
2359
|
+
isHole
|
|
2360
|
+
}) {
|
|
2361
|
+
if (inHole !== isHole) {
|
|
2362
|
+
lineHtml += htmlEscape(chunk);
|
|
2363
|
+
lineHtml += "</span><span";
|
|
2364
|
+
if (isHole) {
|
|
2365
|
+
lineHtml += " class=\"uncovered\"";
|
|
2366
|
+
}
|
|
2367
|
+
lineHtml += ">";
|
|
2368
|
+
chunk = "";
|
|
2369
|
+
inHole = isHole;
|
|
2370
|
+
}
|
|
2371
|
+
chunk += char;
|
|
2372
|
+
});
|
|
2373
|
+
lineHtml += htmlEscape(chunk);
|
|
2374
|
+
break;
|
|
2375
|
+
default:
|
|
2376
|
+
lineHtml += htmlEscape(line);
|
|
2377
|
+
}
|
|
2378
|
+
html += String(`
|
|
1661
2379
|
<pre>
|
|
1662
2380
|
<span class="lineno">
|
|
1663
2381
|
<a href="#${lineId}" id="${lineId}">${String(ii + 1).padStart(5, " ")}.</a>
|
|
1664
2382
|
</span>
|
|
1665
2383
|
<span class="count
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
2384
|
+
${(
|
|
2385
|
+
count <= 0
|
|
2386
|
+
? "uncovered"
|
|
2387
|
+
: ""
|
|
2388
|
+
)}"
|
|
1671
2389
|
>
|
|
1672
|
-
${String(count).padStart(7, " ")}
|
|
2390
|
+
${String(count || "-0").padStart(7, " ")}
|
|
1673
2391
|
</span>
|
|
1674
2392
|
<span>${lineHtml}</span>
|
|
1675
2393
|
</pre>
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
html += `
|
|
2394
|
+
`).replace((
|
|
2395
|
+
/\n/g
|
|
2396
|
+
), "").trim() + "\n";
|
|
2397
|
+
});
|
|
2398
|
+
html += String(`
|
|
1682
2399
|
</div>
|
|
1683
|
-
|
|
2400
|
+
<!-- content end -->
|
|
2401
|
+
`).trim() + "\n";
|
|
2402
|
+
}
|
|
2403
|
+
html += String(`
|
|
2404
|
+
<div class="footer">
|
|
2405
|
+
[
|
|
2406
|
+
This document was created with
|
|
2407
|
+
<a href="https://github.com/jslint-org/jslint">JSLint</a>
|
|
2408
|
+
]
|
|
1684
2409
|
</div>
|
|
1685
2410
|
</body>
|
|
1686
|
-
</html
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
// fs - write *.html
|
|
1692
|
-
moduleFs.promises.writeFile(pathname + ".html", html);
|
|
1693
|
-
if (lineList) {
|
|
1694
|
-
return;
|
|
1695
|
-
}
|
|
1696
|
-
// fs - write coverage.txt
|
|
1697
|
-
console.error("\n" + txt);
|
|
1698
|
-
moduleFs.promises.writeFile((
|
|
1699
|
-
DIR_COVERAGE + "/coverage-report.txt"
|
|
1700
|
-
), txt);
|
|
2411
|
+
</html>
|
|
2412
|
+
`).trim() + "\n";
|
|
2413
|
+
promiseList.push(fsWriteFileWithParents(pathname + ".html", html));
|
|
2414
|
+
if (!modeIndex) {
|
|
2415
|
+
return;
|
|
1701
2416
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
2417
|
+
consoleError("\n" + txt);
|
|
2418
|
+
promiseList.push(fsWriteFileWithParents((
|
|
2419
|
+
coverageDir + "coverage_report.txt"
|
|
2420
|
+
), txt));
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
function pathnameRelativeCwd(pathname) {
|
|
2424
|
+
pathname = modulePath.resolve(pathname).replace((
|
|
2425
|
+
/\\/g
|
|
2426
|
+
), "/");
|
|
2427
|
+
if (!pathname.startsWith(cwd)) {
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
pathname = pathname.slice(cwd.length);
|
|
2431
|
+
return pathname;
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
/*
|
|
2435
|
+
function sentinel() {}
|
|
2436
|
+
*/
|
|
2437
|
+
|
|
2438
|
+
await moduleFsInit();
|
|
2439
|
+
consoleError = consoleError || console.error;
|
|
2440
|
+
cwd = process.cwd().replace((
|
|
2441
|
+
/\\/g
|
|
2442
|
+
), "/") + "/";
|
|
2443
|
+
assertOrThrow(coverageDir, "invalid coverageDir " + coverageDir);
|
|
2444
|
+
coverageDir = modulePath.resolve(coverageDir).replace((
|
|
2445
|
+
/\\/g
|
|
2446
|
+
), "/") + "/";
|
|
2447
|
+
|
|
2448
|
+
processArgv = processArgv.slice();
|
|
2449
|
+
while (processArgv[0] && processArgv[0][0] === "-") {
|
|
2450
|
+
processArgElem = processArgv.shift().split("=");
|
|
2451
|
+
processArgElem[1] = processArgElem.slice(1).join("=");
|
|
2452
|
+
switch (processArgElem[0]) {
|
|
2453
|
+
case "--exclude":
|
|
2454
|
+
fileExcludeList = fileExcludeList.concat(
|
|
2455
|
+
processArgElem[1].split(",")
|
|
2456
|
+
);
|
|
2457
|
+
break;
|
|
2458
|
+
case "--exclude-node-modules":
|
|
2459
|
+
fileIncludeNodeModules = (
|
|
2460
|
+
/0|false|null|undefined/
|
|
2461
|
+
).test(processArgElem[1]);
|
|
2462
|
+
break;
|
|
2463
|
+
case "--include":
|
|
2464
|
+
fileIncludeList = fileIncludeList.concat(
|
|
2465
|
+
processArgElem[1].split(",")
|
|
2466
|
+
);
|
|
2467
|
+
break;
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
if (processArgv.length > 0) {
|
|
2471
|
+
await fsWriteFileWithParents(coverageDir + "/touch.txt", "");
|
|
2472
|
+
await Promise.all(Array.from(
|
|
2473
|
+
await moduleFs.promises.readdir(coverageDir)
|
|
2474
|
+
).map(async function (file) {
|
|
2475
|
+
if ((
|
|
2476
|
+
/^coverage-\d+?-\d+?-\d+?\.json$/
|
|
2477
|
+
).test(file)) {
|
|
2478
|
+
console.error("rm file " + coverageDir + file);
|
|
2479
|
+
await moduleFs.promises.unlink(coverageDir + file);
|
|
2480
|
+
}
|
|
1716
2481
|
}));
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
2482
|
+
exitCode = await new Promise(function (resolve) {
|
|
2483
|
+
moduleChildProcess.spawn((
|
|
2484
|
+
processArgv[0] === "npm"
|
|
2485
|
+
? process.platform.replace("win32", "npm.cmd").replace(
|
|
2486
|
+
process.platform,
|
|
2487
|
+
"npm"
|
|
2488
|
+
)
|
|
2489
|
+
: processArgv[0]
|
|
2490
|
+
), processArgv.slice(1), {
|
|
2491
|
+
env: Object.assign({}, process.env, {
|
|
2492
|
+
NODE_V8_COVERAGE: coverageDir
|
|
2493
|
+
}),
|
|
2494
|
+
stdio: [
|
|
2495
|
+
"ignore", 1, 2
|
|
2496
|
+
]
|
|
2497
|
+
}).on("exit", resolve);
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
v8CoverageObj = await moduleFs.promises.readdir(coverageDir);
|
|
2501
|
+
v8CoverageObj = v8CoverageObj.filter(function (file) {
|
|
2502
|
+
return (
|
|
2503
|
+
/^coverage-\d+?-\d+?-\d+?\.json$/
|
|
2504
|
+
).test(file);
|
|
2505
|
+
});
|
|
2506
|
+
v8CoverageObj = await Promise.all(v8CoverageObj.map(async function (file) {
|
|
2507
|
+
let data = await moduleFs.promises.readFile(coverageDir + file, "utf8");
|
|
2508
|
+
data = JSON.parse(data);
|
|
2509
|
+
data.result = data.result.filter(function (scriptCov) {
|
|
2510
|
+
let pathname = scriptCov.url;
|
|
2511
|
+
if (!pathname.startsWith("file:///")) {
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
pathname = pathnameRelativeCwd(moduleUrl.fileURLToPath(pathname));
|
|
2515
|
+
if (
|
|
2516
|
+
!pathname
|
|
2517
|
+
|| pathname.startsWith("[")
|
|
2518
|
+
|| (
|
|
2519
|
+
!fileIncludeNodeModules
|
|
2520
|
+
&& (
|
|
2521
|
+
/(?:^|\/)node_modules\//m
|
|
2522
|
+
).test(pathname)
|
|
2523
|
+
)
|
|
2524
|
+
|| fileExcludeList.indexOf(pathname) >= 0
|
|
2525
|
+
|| (
|
|
2526
|
+
fileIncludeList.length > 0
|
|
2527
|
+
&& fileIncludeList.indexOf(pathname) === -1
|
|
2528
|
+
)
|
|
2529
|
+
) {
|
|
2530
|
+
return;
|
|
2531
|
+
}
|
|
2532
|
+
scriptCov.url = pathname;
|
|
2533
|
+
return true;
|
|
2534
|
+
});
|
|
2535
|
+
return data;
|
|
2536
|
+
}));
|
|
2537
|
+
v8CoverageObj = v8CoverageListMerge(v8CoverageObj);
|
|
2538
|
+
await fsWriteFileWithParents(
|
|
2539
|
+
coverageDir + "v8_coverage_merged.json",
|
|
2540
|
+
JSON.stringify(v8CoverageObj, undefined, 1)
|
|
2541
|
+
);
|
|
2542
|
+
fileDict = {};
|
|
2543
|
+
await Promise.all(v8CoverageObj.result.map(async function ({
|
|
2544
|
+
functions,
|
|
2545
|
+
url: pathname
|
|
2546
|
+
}) {
|
|
2547
|
+
let lineList;
|
|
2548
|
+
let linesCovered;
|
|
2549
|
+
let linesTotal;
|
|
2550
|
+
let source;
|
|
2551
|
+
source = await moduleFs.promises.readFile(pathname, "utf8");
|
|
2552
|
+
lineList = [{}];
|
|
2553
|
+
source.replace((
|
|
2554
|
+
/^.*$/gm
|
|
2555
|
+
), function (line, startOffset) {
|
|
2556
|
+
lineList[lineList.length - 1].endOffset = startOffset - 1;
|
|
2557
|
+
lineList.push({
|
|
2558
|
+
count: -1,
|
|
2559
|
+
endOffset: 0,
|
|
2560
|
+
holeList: [],
|
|
2561
|
+
line,
|
|
2562
|
+
startOffset
|
|
2563
|
+
});
|
|
2564
|
+
return "";
|
|
2565
|
+
});
|
|
2566
|
+
lineList.shift();
|
|
2567
|
+
lineList[lineList.length - 1].endOffset = source.length;
|
|
2568
|
+
functions.reverse().forEach(function ({
|
|
2569
|
+
ranges
|
|
1724
2570
|
}) {
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
!pathname.startsWith(cwd)
|
|
1742
|
-
|| pathname.startsWith(cwd + "[")
|
|
1743
|
-
|| (
|
|
1744
|
-
process.env.npm_config_mode_coverage !== "all"
|
|
1745
|
-
&& pathname.indexOf("/node_modules/") >= 0
|
|
2571
|
+
ranges.reverse().forEach(function ({
|
|
2572
|
+
count,
|
|
2573
|
+
endOffset,
|
|
2574
|
+
startOffset
|
|
2575
|
+
}, ii, list) {
|
|
2576
|
+
lineList.forEach(function (elem) {
|
|
2577
|
+
if (!(
|
|
2578
|
+
(
|
|
2579
|
+
elem.startOffset <= startOffset
|
|
2580
|
+
&& startOffset <= elem.endOffset
|
|
2581
|
+
) || (
|
|
2582
|
+
elem.startOffset <= endOffset
|
|
2583
|
+
&& endOffset <= elem.endOffset
|
|
2584
|
+
) || (
|
|
2585
|
+
startOffset <= elem.startOffset
|
|
2586
|
+
&& elem.endOffset <= endOffset
|
|
1746
2587
|
)
|
|
1747
|
-
|
|
2588
|
+
)) {
|
|
1748
2589
|
return;
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
});
|
|
1766
|
-
lineList.shift();
|
|
1767
|
-
lineList[lineList.length - 1].endOffset = src.length;
|
|
1768
|
-
functions.reverse().forEach(function ({
|
|
1769
|
-
ranges
|
|
1770
|
-
}) {
|
|
1771
|
-
ranges.reverse().forEach(function ({
|
|
1772
|
-
count,
|
|
1773
|
-
endOffset,
|
|
1774
|
-
startOffset
|
|
1775
|
-
}, ii, list) {
|
|
1776
|
-
lineList.forEach(function (elem) {
|
|
1777
|
-
if (!(
|
|
1778
|
-
(
|
|
1779
|
-
elem.startOffset <= startOffset
|
|
1780
|
-
&& startOffset <= elem.endOffset
|
|
1781
|
-
) || (
|
|
1782
|
-
elem.startOffset <= endOffset
|
|
1783
|
-
&& endOffset <= elem.endOffset
|
|
1784
|
-
) || (
|
|
1785
|
-
startOffset <= elem.startOffset
|
|
1786
|
-
&& elem.endOffset <= endOffset
|
|
1787
|
-
)
|
|
1788
|
-
)) {
|
|
1789
|
-
return;
|
|
1790
|
-
}
|
|
1791
|
-
// handle root-range
|
|
1792
|
-
if (ii + 1 === list.length) {
|
|
1793
|
-
if (elem.count === -1) {
|
|
1794
|
-
elem.count = count;
|
|
1795
|
-
}
|
|
1796
|
-
return;
|
|
1797
|
-
}
|
|
1798
|
-
// handle non-root-range
|
|
1799
|
-
if (elem.count !== 0) {
|
|
1800
|
-
elem.count = Math.max(count, elem.count);
|
|
1801
|
-
}
|
|
1802
|
-
if (count === 0) {
|
|
1803
|
-
elem.count = 0;
|
|
1804
|
-
elem.holeList.push([
|
|
1805
|
-
startOffset, endOffset
|
|
1806
|
-
]);
|
|
1807
|
-
}
|
|
1808
|
-
});
|
|
1809
|
-
});
|
|
1810
|
-
});
|
|
1811
|
-
linesTotal = lineList.length;
|
|
1812
|
-
linesCovered = lineList.filter(function ({
|
|
1813
|
-
count
|
|
1814
|
-
}) {
|
|
1815
|
-
return count > 0;
|
|
1816
|
-
}).length;
|
|
1817
|
-
await moduleFs.promises.mkdir((
|
|
1818
|
-
modulePath.dirname(DIR_COVERAGE + pathname)
|
|
1819
|
-
), {
|
|
1820
|
-
recursive: true
|
|
1821
|
-
});
|
|
1822
|
-
await htmlRender({
|
|
1823
|
-
fileList: [
|
|
1824
|
-
{
|
|
1825
|
-
linesCovered,
|
|
1826
|
-
linesTotal,
|
|
1827
|
-
pathname
|
|
1828
|
-
}
|
|
1829
|
-
],
|
|
1830
|
-
lineList,
|
|
1831
|
-
pathname: DIR_COVERAGE + pathname
|
|
2590
|
+
}
|
|
2591
|
+
if (ii + 1 === list.length) {
|
|
2592
|
+
if (elem.count === -1) {
|
|
2593
|
+
elem.count = count;
|
|
2594
|
+
}
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2597
|
+
if (elem.count !== 0) {
|
|
2598
|
+
elem.count = Math.max(count, elem.count);
|
|
2599
|
+
}
|
|
2600
|
+
if (count === 0) {
|
|
2601
|
+
elem.count = 0;
|
|
2602
|
+
elem.holeList.push([
|
|
2603
|
+
startOffset, endOffset
|
|
2604
|
+
]);
|
|
2605
|
+
}
|
|
1832
2606
|
});
|
|
1833
|
-
|
|
1834
|
-
lineList,
|
|
1835
|
-
linesCovered,
|
|
1836
|
-
linesTotal,
|
|
1837
|
-
pathname,
|
|
1838
|
-
src
|
|
1839
|
-
};
|
|
1840
|
-
}));
|
|
1841
|
-
await htmlRender({
|
|
1842
|
-
fileList: Object.keys(fileDict).sort().map(function (pathname) {
|
|
1843
|
-
return fileDict[pathname];
|
|
1844
|
-
}),
|
|
1845
|
-
pathname: DIR_COVERAGE + "index"
|
|
2607
|
+
});
|
|
1846
2608
|
});
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2609
|
+
linesTotal = lineList.length;
|
|
2610
|
+
linesCovered = lineList.filter(function ({
|
|
2611
|
+
count
|
|
2612
|
+
}) {
|
|
2613
|
+
return count > 0;
|
|
2614
|
+
}).length;
|
|
2615
|
+
await moduleFs.promises.mkdir((
|
|
2616
|
+
modulePath.dirname(coverageDir + pathname)
|
|
2617
|
+
), {
|
|
2618
|
+
recursive: true
|
|
2619
|
+
});
|
|
2620
|
+
fileDict[pathname] = {
|
|
2621
|
+
lineList,
|
|
2622
|
+
linesCovered,
|
|
2623
|
+
linesTotal,
|
|
2624
|
+
modeCoverageIgnoreFile: (
|
|
2625
|
+
(
|
|
2626
|
+
/^\/\*coverage-ignore-file\*\/$/m
|
|
2627
|
+
).test(source.slice(0, 65536))
|
|
2628
|
+
? "(ignore)"
|
|
2629
|
+
: ""
|
|
2630
|
+
),
|
|
2631
|
+
pathname
|
|
2632
|
+
};
|
|
2633
|
+
htmlRender({
|
|
2634
|
+
fileList: [
|
|
2635
|
+
fileDict[pathname]
|
|
2636
|
+
],
|
|
2637
|
+
lineList,
|
|
2638
|
+
pathname: coverageDir + pathname
|
|
2639
|
+
});
|
|
2640
|
+
}));
|
|
2641
|
+
htmlRender({
|
|
2642
|
+
fileList: Object.keys(fileDict).sort().map(function (pathname) {
|
|
2643
|
+
return fileDict[pathname];
|
|
2644
|
+
}),
|
|
2645
|
+
modeIndex: true,
|
|
2646
|
+
pathname: coverageDir + "index"
|
|
2647
|
+
});
|
|
2648
|
+
await Promise.all(promiseList);
|
|
2649
|
+
assertOrThrow(
|
|
2650
|
+
exitCode === 0,
|
|
2651
|
+
"v8CoverageReportCreate - nonzero exitCode " + exitCode
|
|
2652
|
+
);
|
|
2653
|
+
}
|
|
2654
|
+
v8CoverageReportCreate({
|
|
2655
|
+
coverageDir: ".artifact/coverage",
|
|
2656
|
+
processArgv: process.argv.slice(2)
|
|
2657
|
+
});
|
|
2658
|
+
' 0 "$@" # '
|
|
1853
2659
|
)}
|
|
1854
2660
|
|
|
1855
2661
|
shRunWithScreenshotTxt() {(set -e
|
|
@@ -1866,9 +2672,10 @@ shRunWithScreenshotTxt() {(set -e
|
|
|
1866
2672
|
"$@" 2>&1 || printf "$?\n" > "$SCREENSHOT_SVG.exit_code"
|
|
1867
2673
|
) | tee "$SCREENSHOT_SVG.txt"
|
|
1868
2674
|
EXIT_CODE="$(cat "$SCREENSHOT_SVG.exit_code")"
|
|
1869
|
-
printf "shRunWithScreenshotTxt - EXIT_CODE=$EXIT_CODE\n"
|
|
2675
|
+
printf "shRunWithScreenshotTxt - EXIT_CODE=$EXIT_CODE - $SCREENSHOT_SVG\n" \
|
|
2676
|
+
1>&2
|
|
1870
2677
|
# format text-output
|
|
1871
|
-
node --input-type=module
|
|
2678
|
+
node --input-type=module --eval '
|
|
1872
2679
|
import moduleFs from "fs";
|
|
1873
2680
|
(async function () {
|
|
1874
2681
|
let result = await moduleFs.promises.readFile(
|
|
@@ -1935,7 +2742,7 @@ ${result}
|
|
|
1935
2742
|
`).trim() + "\n";
|
|
1936
2743
|
moduleFs.promises.writeFile(process.argv[1], result);
|
|
1937
2744
|
}());
|
|
1938
|
-
' "$SCREENSHOT_SVG" #
|
|
2745
|
+
' "$SCREENSHOT_SVG" # '
|
|
1939
2746
|
printf "shRunWithScreenshotTxt - wrote - $SCREENSHOT_SVG\n"
|
|
1940
2747
|
# cleanup
|
|
1941
2748
|
rm "$SCREENSHOT_SVG.exit_code" "$SCREENSHOT_SVG.txt"
|
|
@@ -1943,7 +2750,11 @@ ${result}
|
|
|
1943
2750
|
)}
|
|
1944
2751
|
|
|
1945
2752
|
shCiMain() {(set -e
|
|
1946
|
-
# run $@
|
|
2753
|
+
# this function will run $@
|
|
2754
|
+
if [ "$1" = "" ]
|
|
2755
|
+
then
|
|
2756
|
+
return
|
|
2757
|
+
fi
|
|
1947
2758
|
# run "$@" with winpty
|
|
1948
2759
|
export CI_UNAME="${CI_UNAME:-$(uname)}"
|
|
1949
2760
|
case "$CI_UNAME" in
|
|
@@ -1951,7 +2762,7 @@ shCiMain() {(set -e
|
|
|
1951
2762
|
if [ ! "$CI_WINPTY" ] && [ "$1" != shHttpFileServer ]
|
|
1952
2763
|
then
|
|
1953
2764
|
export CI_WINPTY=1
|
|
1954
|
-
winpty -Xallow-non-tty -Xplain sh
|
|
2765
|
+
winpty -Xallow-non-tty -Xplain sh "$0" "$@"
|
|
1955
2766
|
return
|
|
1956
2767
|
fi
|
|
1957
2768
|
;;
|
|
@@ -1965,4 +2776,7 @@ shCiMain() {(set -e
|
|
|
1965
2776
|
"$@"
|
|
1966
2777
|
)}
|
|
1967
2778
|
|
|
2779
|
+
# init ubuntu .bashrc
|
|
2780
|
+
shBashrcDebianInit || return "$?"
|
|
2781
|
+
|
|
1968
2782
|
shCiMain "$@"
|