fake-node 0.2.0 → 0.3.0
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/LICENSE +21 -0
- package/README.md +3 -0
- package/lib/index.d.ts +59 -0
- package/{index.js → lib/index.js} +114 -50
- package/lib/os.d.ts +191 -0
- package/lib/os.js +271 -0
- package/lib/process.d.ts +103 -0
- package/lib/process.js +223 -0
- package/lib/querystring.d.ts +7 -0
- package/lib/querystring.js +38 -0
- package/lib/web_only_globals.json +1049 -0
- package/package.json +9 -13
- package/src/fs.ts +517 -0
- package/src/index.ts +229 -0
- package/src/os.ts +266 -0
- package/src/process.ts +263 -0
- package/src/querystring.ts +36 -0
- package/src/util.ts +408 -0
- package/index.ts +0 -148
- package/tsconfig.json +0 -10
- /package/{web_only_globals.json → src/web_only_globals.json} +0 -0
package/src/index.ts
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
|
2
|
+
import * as module_os from './os';
|
3
|
+
import * as module_process from './process';
|
4
|
+
import * as module_punycode from 'punycode/';
|
5
|
+
import * as module_querystring from './querystring';
|
6
|
+
import WEB_ONLY_GLOBALS from './web_only_globals.json';
|
7
|
+
|
8
|
+
|
9
|
+
const DEFAULT_GLOBALS = Object.defineProperties({}, Object.fromEntries(WEB_ONLY_GLOBALS.map((name: string) => [name, {get(): void {throw new ReferenceError(`${name} is not defined`);}}])));
|
10
|
+
|
11
|
+
const BUILTIN_MODULES: [string, any][] = [
|
12
|
+
['os', module_os],
|
13
|
+
['process', module_process],
|
14
|
+
['querystring', module_querystring],
|
15
|
+
['punycode', module_punycode],
|
16
|
+
];
|
17
|
+
|
18
|
+
const DEFAULT_ENV = {
|
19
|
+
PATH: '/usr/local/bin:/usr/bin:/bin',
|
20
|
+
SHLVL: '1',
|
21
|
+
SHELL: '/bin/bash',
|
22
|
+
TERM: 'none',
|
23
|
+
PS1: '',
|
24
|
+
PS2: '> ',
|
25
|
+
HISTFILE: '~/.bash_history',
|
26
|
+
EDITOR: 'vim',
|
27
|
+
VISUAL: 'vim',
|
28
|
+
LANG: 'en_US.utf8',
|
29
|
+
HOSTNAME: 'fake-node',
|
30
|
+
TMPDIR: '/tmp',
|
31
|
+
};
|
32
|
+
|
33
|
+
|
34
|
+
export class Process {
|
35
|
+
|
36
|
+
fakeNode: FakeNode;
|
37
|
+
|
38
|
+
pid: number;
|
39
|
+
priority: number = 0;
|
40
|
+
|
41
|
+
uid: number = 0;
|
42
|
+
gid: number = 0;
|
43
|
+
groups: number[] = [];
|
44
|
+
cwd: string;
|
45
|
+
umask: number = 0o6440;
|
46
|
+
|
47
|
+
argv: string[] = [];
|
48
|
+
argv0: string = '';
|
49
|
+
execArgv: string[] = [];
|
50
|
+
execArgv0: string = '/usr/bin/local/node';
|
51
|
+
|
52
|
+
path: string;
|
53
|
+
module: false | string;
|
54
|
+
code: string;
|
55
|
+
|
56
|
+
constructor(fakeNode: FakeNode, {path = '', code, module}: {path?: string, code: string, module?: false | string}) {
|
57
|
+
this.fakeNode = fakeNode;
|
58
|
+
this.pid = fakeNode.nextPid;
|
59
|
+
fakeNode.nextPid++;
|
60
|
+
fakeNode.processes.set(this.pid, this);
|
61
|
+
this.code = code;
|
62
|
+
this.path = path;
|
63
|
+
this.cwd = path.split('/').slice(0, -1).join('/');
|
64
|
+
this.module = module ?? false;
|
65
|
+
}
|
66
|
+
|
67
|
+
get env(): {[key: string]: string} {
|
68
|
+
return this.fakeNode.getenv(this.pid);
|
69
|
+
}
|
70
|
+
|
71
|
+
run(): void {
|
72
|
+
let code: string;
|
73
|
+
if (this.module) {
|
74
|
+
code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){__fakeNode__.modules.set('${this.module},(function(){${this.code};return module.exports;})());}`;
|
75
|
+
} else {
|
76
|
+
code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){(function(){${this.code}})();}`;
|
77
|
+
}
|
78
|
+
let elt = document.createElement('script');
|
79
|
+
elt.textContent = code;
|
80
|
+
document.body.appendChild(elt);
|
81
|
+
}
|
82
|
+
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
export class FakeNode {
|
87
|
+
|
88
|
+
version: string = '0.3.0';
|
89
|
+
|
90
|
+
static nextId: number = 0;
|
91
|
+
id: number;
|
92
|
+
globalName: string;
|
93
|
+
|
94
|
+
globalenv: {[key: string]: string} = DEFAULT_ENV;
|
95
|
+
|
96
|
+
modules: Map<string, unknown> = new Map();
|
97
|
+
|
98
|
+
globals: {[key: string]: unknown};
|
99
|
+
|
100
|
+
processes: Map<number, Process> = new Map();
|
101
|
+
nextPid: number = 3;
|
102
|
+
|
103
|
+
window: Window = window;
|
104
|
+
|
105
|
+
errorCallbacks: (Function | undefined)[] = [];
|
106
|
+
|
107
|
+
constructor() {
|
108
|
+
this.id = FakeNode.nextId;
|
109
|
+
FakeNode.nextId++;
|
110
|
+
this.globalName = '__fakeNode_' + this.id + '__';
|
111
|
+
// @ts-ignore
|
112
|
+
globalThis[this.globalName] = this;
|
113
|
+
this.globals = {__fakeNode__: this};
|
114
|
+
Object.assign(this.globals, DEFAULT_GLOBALS);
|
115
|
+
window.addEventListener('error', ({error}) => this.onError(error));
|
116
|
+
window.addEventListener('unhandledrejection', ({reason}) => reason instanceof Error ? this.onError(reason) : this.onError(new Error(String(reason))));
|
117
|
+
for (const [name, module] of BUILTIN_MODULES) {
|
118
|
+
this.addModuleFromValue(name, module);
|
119
|
+
this.addModuleFromValue('node:' + name, module);
|
120
|
+
this.addModuleFromValue('fake-node:' + name, module);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
require(module: string): unknown {
|
125
|
+
if (this.modules.has(module)) {
|
126
|
+
return this.modules.get(module);
|
127
|
+
} else {
|
128
|
+
throw new Error(`cannot find module '${module}'`);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
getGlobals(pid: number): object {
|
133
|
+
const process = this.processes.get(pid);
|
134
|
+
if (process === undefined) {
|
135
|
+
throw new TypeError(`nonexistent PID in FakeNode.getGlobals call: ${pid}. If you do not know why this occured, it is probably a bug in fake-node. Please report it at https://github.com/speedydelete/fake-node/issues.`);
|
136
|
+
}
|
137
|
+
let scope: {[key: string]: unknown} = {};
|
138
|
+
Object.assign(scope, this.globals);
|
139
|
+
scope.global = scope;
|
140
|
+
scope.globalThis = scope;
|
141
|
+
scope.__fakeNode_process__ = process;
|
142
|
+
scope.require = this.require.bind(this);
|
143
|
+
if (process.path !== '') {
|
144
|
+
const pathParts = process.path.split('/');
|
145
|
+
scope.__dirname = pathParts.slice(0, -1).join('/');
|
146
|
+
scope.__filename = pathParts[pathParts.length - 1];
|
147
|
+
}
|
148
|
+
if (process.module !== false) {
|
149
|
+
scope.module = {
|
150
|
+
exports: {},
|
151
|
+
};
|
152
|
+
// @ts-ignore
|
153
|
+
scope.exports = scope.module.exports;
|
154
|
+
}
|
155
|
+
return scope;
|
156
|
+
}
|
157
|
+
|
158
|
+
getenv(pid: number): {[key: string]: string} {
|
159
|
+
let env = Object.create(this.globalenv);
|
160
|
+
const process = this.processes.get(pid);
|
161
|
+
if (process === undefined) {
|
162
|
+
throw new TypeError(`invalid PID: ${pid}`);
|
163
|
+
}
|
164
|
+
env.USER = this.getUserFromUID(process.uid);
|
165
|
+
return env;
|
166
|
+
}
|
167
|
+
|
168
|
+
run(code: string): void {
|
169
|
+
(new Process(this, {code, path: '/'})).run();
|
170
|
+
}
|
171
|
+
|
172
|
+
addModule(name: string, code: string): void {
|
173
|
+
(new Process(this, {code, path: '/', module: name})).run();
|
174
|
+
}
|
175
|
+
|
176
|
+
addModuleFromValue(name: string, module: unknown): void {
|
177
|
+
this.modules.set(name, module);
|
178
|
+
}
|
179
|
+
|
180
|
+
getUserFromUID(uid: number | string): string {
|
181
|
+
if (typeof uid === 'string') {
|
182
|
+
return uid;
|
183
|
+
} else {
|
184
|
+
return 'root';
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
getUserFromGID(gid: number | string): string {
|
189
|
+
if (typeof gid === 'string') {
|
190
|
+
return gid;
|
191
|
+
} else {
|
192
|
+
return 'root';
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
getUIDFromUser(user: string | number): number {
|
197
|
+
if (typeof user === 'number') {
|
198
|
+
return user;
|
199
|
+
} else {
|
200
|
+
return 0;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
getGIDFromGroup(group: string | number): number {
|
205
|
+
if (typeof group === 'number') {
|
206
|
+
return group;
|
207
|
+
} else {
|
208
|
+
return 0;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
onError(error: Error): void {
|
213
|
+
for (const callback of this.errorCallbacks) {
|
214
|
+
if (callback !== undefined) {
|
215
|
+
callback(error);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
addErrorCallback(callback: Function): number {
|
221
|
+
this.errorCallbacks.push(callback);
|
222
|
+
return this.errorCallbacks.length - 1;
|
223
|
+
}
|
224
|
+
|
225
|
+
removeErrorCallback(callbackID: number): void {
|
226
|
+
this.errorCallbacks[callbackID] = undefined;
|
227
|
+
}
|
228
|
+
|
229
|
+
}
|
package/src/os.ts
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
|
2
|
+
export const EOL = '\n';
|
3
|
+
|
4
|
+
export function availableParallelism(): number {
|
5
|
+
return 1;
|
6
|
+
}
|
7
|
+
|
8
|
+
export function arch(): string {
|
9
|
+
return 'web';
|
10
|
+
}
|
11
|
+
|
12
|
+
enum signals {
|
13
|
+
SIGHUP = 1,
|
14
|
+
SIGINT,
|
15
|
+
SIGQUIT,
|
16
|
+
SIGILL,
|
17
|
+
SIGTRAP,
|
18
|
+
SIGABRT,
|
19
|
+
SIGIOT = SIGABRT,
|
20
|
+
SIGBUS,
|
21
|
+
SIGFPE,
|
22
|
+
SIGKILL,
|
23
|
+
SIGUSR1,
|
24
|
+
SIGUSR2,
|
25
|
+
SIGSEGV,
|
26
|
+
SIGPIPE,
|
27
|
+
SIGALRM,
|
28
|
+
SIGTERM,
|
29
|
+
SIGCHLD,
|
30
|
+
SIGSTKFLT,
|
31
|
+
SIGCONT,
|
32
|
+
SIGSTOP,
|
33
|
+
SIGTSTP,
|
34
|
+
SIGBREAK,
|
35
|
+
SIGTTIN,
|
36
|
+
SIGTTOU,
|
37
|
+
SIGURG,
|
38
|
+
SIGXCPU,
|
39
|
+
SIGXFSZ,
|
40
|
+
SIGVTALRM,
|
41
|
+
SIGPROF,
|
42
|
+
SIGWINCH,
|
43
|
+
SIGIO,
|
44
|
+
SIGPOLL = SIGIO,
|
45
|
+
SIGLOST,
|
46
|
+
SIGPWR,
|
47
|
+
SIGINFO = SIGPWR,
|
48
|
+
SIGSYS,
|
49
|
+
SIGUNUSED = SIGSYS,
|
50
|
+
}
|
51
|
+
|
52
|
+
enum errno {
|
53
|
+
E2BIG,
|
54
|
+
EACCES,
|
55
|
+
EADDRINUSE,
|
56
|
+
EADDRNONOTAVAIL,
|
57
|
+
EAFNOSUPPORT,
|
58
|
+
EAGAIN,
|
59
|
+
EALREADY,
|
60
|
+
EBADF,
|
61
|
+
EBADMSG,
|
62
|
+
EBUSY,
|
63
|
+
ECANCELED,
|
64
|
+
ECHILD,
|
65
|
+
ECONNABORTED,
|
66
|
+
ECONNREFUSED,
|
67
|
+
ECONNRESET,
|
68
|
+
EDEADLK,
|
69
|
+
EDESTADDRREQ,
|
70
|
+
EDOM,
|
71
|
+
EDQUOT,
|
72
|
+
EEXIST,
|
73
|
+
EFAULT,
|
74
|
+
EFBIG,
|
75
|
+
EHOSTUNREACH,
|
76
|
+
EIDRM,
|
77
|
+
EILSEQ,
|
78
|
+
EINPROGRESS,
|
79
|
+
EINTR,
|
80
|
+
EINVAL,
|
81
|
+
EIO,
|
82
|
+
EISCONN,
|
83
|
+
EISDIR,
|
84
|
+
ELOOP,
|
85
|
+
EMFILE,
|
86
|
+
EMLINK,
|
87
|
+
EMGSIZE,
|
88
|
+
EMULTIHOP,
|
89
|
+
ENAMETOOLONG,
|
90
|
+
ENETDOWN,
|
91
|
+
ENETRESET,
|
92
|
+
ENETUNREACH,
|
93
|
+
ENFILE,
|
94
|
+
ENOBUFS,
|
95
|
+
ENODATA,
|
96
|
+
ENODEV,
|
97
|
+
ENOENT,
|
98
|
+
ENOEXEC,
|
99
|
+
ENOLCK,
|
100
|
+
ENOLINK,
|
101
|
+
ENOMEM,
|
102
|
+
ENOMSG,
|
103
|
+
ENOPROTOOPT,
|
104
|
+
ENOSPC,
|
105
|
+
ENOSR,
|
106
|
+
ENOSTR,
|
107
|
+
ENOSYS,
|
108
|
+
ENOTCONN,
|
109
|
+
ENOTDIR,
|
110
|
+
ENOTEMPTY,
|
111
|
+
ENOTSOCK,
|
112
|
+
ENOTSUP,
|
113
|
+
ENOTTY,
|
114
|
+
ENXIO,
|
115
|
+
EOPNOTSUPP,
|
116
|
+
EOVERFLOW,
|
117
|
+
EPERM,
|
118
|
+
EPIPE,
|
119
|
+
EPROTO,
|
120
|
+
EPROTONOSUPPORT,
|
121
|
+
EPROTOTYPE,
|
122
|
+
ERANGE,
|
123
|
+
EROFS,
|
124
|
+
ESPIPE,
|
125
|
+
ESRCH,
|
126
|
+
ESTALE,
|
127
|
+
ETIME,
|
128
|
+
ETIMEDOUT,
|
129
|
+
ETXTBSY,
|
130
|
+
EWOULDBLOCK,
|
131
|
+
EXDEV,
|
132
|
+
}
|
133
|
+
|
134
|
+
enum dlopen {
|
135
|
+
RTLD_LAZY = 1,
|
136
|
+
RTLD_NOW,
|
137
|
+
RTLD_GLOBAL,
|
138
|
+
RTLD_LOCAL,
|
139
|
+
RTLD_DEEPBIND,
|
140
|
+
}
|
141
|
+
|
142
|
+
enum priority {
|
143
|
+
PRIORITY_LOW = 1,
|
144
|
+
PRIORITY_BELOW_NORMAL,
|
145
|
+
PRIORITY_NORMAL,
|
146
|
+
PRIORITY_ABOVE_NORMAL,
|
147
|
+
PRIORITY_HIGH,
|
148
|
+
PRIORITY_HIGHEST,
|
149
|
+
}
|
150
|
+
|
151
|
+
export const constants = {signals, errno, dlopen, priority};
|
152
|
+
|
153
|
+
export function cpus(): {model: string, speed: number, times: {user: number, nice: number, sys: number, idle: number, irq: number}}[] {
|
154
|
+
return [];
|
155
|
+
}
|
156
|
+
|
157
|
+
export const devNull = '/dev/null';
|
158
|
+
|
159
|
+
export function endianness(): string {
|
160
|
+
return 'LE';
|
161
|
+
}
|
162
|
+
|
163
|
+
export function freemem(): number {
|
164
|
+
return Infinity;
|
165
|
+
}
|
166
|
+
|
167
|
+
export function getPriority(pid: number = -1): number {
|
168
|
+
if (pid === -1) {
|
169
|
+
return __fakeNode_process__.priority;
|
170
|
+
}
|
171
|
+
const process = __fakeNode__.processes.get(pid);
|
172
|
+
if (process === undefined) {
|
173
|
+
throw new TypeError(`invalid PID: ${pid}`);
|
174
|
+
}
|
175
|
+
return process.priority;
|
176
|
+
}
|
177
|
+
|
178
|
+
export function homedir(): string {
|
179
|
+
return '/home/' + __fakeNode__.getUserFromUID(__fakeNode_process__.uid);
|
180
|
+
}
|
181
|
+
|
182
|
+
export function hostname(): string {
|
183
|
+
return __fakeNode__.globalenv.HOSTNAME;
|
184
|
+
}
|
185
|
+
|
186
|
+
export function loadavg(): [number, number, number] {
|
187
|
+
return [-1, -1, -1];
|
188
|
+
}
|
189
|
+
|
190
|
+
export function machine(): string {
|
191
|
+
return 'x86_64';
|
192
|
+
}
|
193
|
+
|
194
|
+
export function networkInterfaces(): {[key: string]: {address: string, netmask: string, family: 'IPV4' | 'IPV6', mac: string, internal: boolean, scopeid: number, cidr: string}} {
|
195
|
+
return {};
|
196
|
+
}
|
197
|
+
|
198
|
+
export function platform(): string {
|
199
|
+
const data = __fakeNode__.window.navigator.userAgent.slice('Mozilla/5.0 ('.length, navigator.userAgent.indexOf(')'));
|
200
|
+
if (data.includes('Windows')) {
|
201
|
+
return 'win32';
|
202
|
+
} else if (data.includes('Linux')) {
|
203
|
+
return 'linux';
|
204
|
+
} else if (data.includes('Mac')) {
|
205
|
+
return 'darwin';
|
206
|
+
} else {
|
207
|
+
return 'unknown';
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
export function release(): string {
|
212
|
+
return platform();
|
213
|
+
}
|
214
|
+
|
215
|
+
export function setPriority(priority: number): void;
|
216
|
+
export function setPriority(pid: number, priority: number): void;
|
217
|
+
export function setPriority(pid_or_priority: number, priority?: number): void {
|
218
|
+
if (priority === undefined) {
|
219
|
+
__fakeNode_process__.priority = pid_or_priority;
|
220
|
+
} else {
|
221
|
+
const process = __fakeNode__.processes.get(pid_or_priority);
|
222
|
+
if (process === undefined) {
|
223
|
+
throw new TypeError(`invalid PID: ${pid_or_priority}`);
|
224
|
+
}
|
225
|
+
process.priority = priority;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
export function tmpdir(): string {
|
230
|
+
return __fakeNode__.globalenv.TMPDIR;
|
231
|
+
}
|
232
|
+
|
233
|
+
export function totalmem(): number {
|
234
|
+
return Infinity;
|
235
|
+
}
|
236
|
+
|
237
|
+
export function type(): string {
|
238
|
+
const data = navigator.userAgent.slice('Mozilla/5.0 ('.length, navigator.userAgent.indexOf(')'));
|
239
|
+
if (data.includes('Windows NT')) {
|
240
|
+
return 'Windows_NT';
|
241
|
+
} else if (data.includes('Linux')) {
|
242
|
+
return 'Linux';
|
243
|
+
} else if (data.includes('Mac')) {
|
244
|
+
return 'Darwin';
|
245
|
+
} else {
|
246
|
+
return 'unknown';
|
247
|
+
}
|
248
|
+
}
|
249
|
+
|
250
|
+
export function uptime(): number {
|
251
|
+
return (__fakeNode__.window.performance.now() - __fakeNode__.window.performance.timeOrigin) / 1000;
|
252
|
+
}
|
253
|
+
|
254
|
+
export function userInfo(): {username: string, uid: number, gid: number, shell: string, homedir: string} {
|
255
|
+
return {
|
256
|
+
username: __fakeNode_process__.fakeNode.getUserFromUID(__fakeNode_process__.uid),
|
257
|
+
uid: __fakeNode_process__.uid,
|
258
|
+
gid: __fakeNode_process__.gid,
|
259
|
+
shell: '/bin/sh',
|
260
|
+
homedir: homedir(),
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
export function version(): string {
|
265
|
+
return __fakeNode__.version;
|
266
|
+
}
|