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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 speedydelete
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ ## fake-node
2
+
3
+ A version of node that works in the browser.
package/lib/index.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ export declare class Process {
2
+ fakeNode: FakeNode;
3
+ pid: number;
4
+ priority: number;
5
+ uid: number;
6
+ gid: number;
7
+ groups: number[];
8
+ cwd: string;
9
+ umask: number;
10
+ argv: string[];
11
+ argv0: string;
12
+ execArgv: string[];
13
+ execArgv0: string;
14
+ path: string;
15
+ module: false | string;
16
+ code: string;
17
+ constructor(fakeNode: FakeNode, { path, code, module }: {
18
+ path?: string;
19
+ code: string;
20
+ module?: false | string;
21
+ });
22
+ get env(): {
23
+ [key: string]: string;
24
+ };
25
+ run(): void;
26
+ }
27
+ export declare class FakeNode {
28
+ version: string;
29
+ static nextId: number;
30
+ id: number;
31
+ globalName: string;
32
+ globalenv: {
33
+ [key: string]: string;
34
+ };
35
+ modules: Map<string, unknown>;
36
+ globals: {
37
+ [key: string]: unknown;
38
+ };
39
+ processes: Map<number, Process>;
40
+ nextPid: number;
41
+ window: Window;
42
+ errorCallbacks: (Function | undefined)[];
43
+ constructor();
44
+ require(module: string): unknown;
45
+ getGlobals(pid: number): object;
46
+ getenv(pid: number): {
47
+ [key: string]: string;
48
+ };
49
+ run(code: string): void;
50
+ addModule(name: string, code: string): void;
51
+ addModuleFromValue(name: string, module: unknown): void;
52
+ getUserFromUID(uid: number | string): string;
53
+ getUserFromGID(gid: number | string): string;
54
+ getUIDFromUser(user: string | number): number;
55
+ getGIDFromGroup(group: string | number): number;
56
+ onError(error: Error): void;
57
+ addErrorCallback(callback: Function): number;
58
+ removeErrorCallback(callbackID: number): void;
59
+ }
@@ -37,37 +37,48 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.FakeNode = exports.Process = void 0;
40
- const assert_1 = __importDefault(require("assert"));
41
- const module_buffer = __importStar(require("buffer"));
42
- // @ts-ignore
43
- const module_path = __importStar(require("path"));
44
- const module_punycode = __importStar(require("punycode"));
45
- const module_querystring = __importStar(require("querystring"));
46
- // @ts-ignore
47
- const module_readline = __importStar(require("readline"));
48
- // @ts-ignore
49
- const module_stream = __importStar(require("stream"));
50
- // @ts-ignore
51
- const module_string_decoder = __importStar(require("string_decoder"));
52
- const module_test = __importStar(require("test"));
53
- // @ts-ignore
54
- const module_url = __importStar(require("url"));
55
- // @ts-ignore
56
- const module_util = __importStar(require("util"));
40
+ const module_os = __importStar(require("./os"));
41
+ const module_process = __importStar(require("./process"));
42
+ const module_punycode = __importStar(require("punycode/"));
43
+ const module_querystring = __importStar(require("./querystring"));
57
44
  const web_only_globals_json_1 = __importDefault(require("./web_only_globals.json"));
58
- // todo: properly implement eval
59
- const DEFAULT_GLOBALS = { Infinity, NaN, undefined, eval, isFinite, isNaN, parseFloat, parseInt, decodeURI, decodeURIComponent, encodeURI, encodeURIComponent, escape, unescape, Object, Function, Boolean, Symbol, Error, AggregateError, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, Number, BigInt, Math, Date, String, RegExp, Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, BigUint64Array, Float32Array, Float64Array, Map, Set, WeakMap, WeakSet, ArrayBuffer, SharedArrayBuffer, DataView, Atomics, JSON, WeakRef, FinalizationRegistry, Promise, Reflect, Proxy, Intl, AbortController, Blob, ByteLengthQueuingStrategy, atob, BroadcastChannel, btoa, clearInterval, clearTimeout, CloseEvent, CompressionStream, console, CountQueuingStrategy, Crypto, crypto, CryptoKey, CustomEvent, DecompressionStream, Event, EventSource, EventTarget, fetch, FormData, Headers, localStorage, MessageChannel, MessageEvent, MessagePort, Navigator, navigator, PerformanceEntry, PerformanceMark, PerformanceMeasure, PerformanceObserver, PerformanceObserverEntryList, performance, queueMicrotask, ReadableByteStreamController, Response, Request, sessionStorage, setInterval, setTimeout, Storage, structuredClone, SubtleCrypto, DOMException, TextDecoder, TextDecoderStream, TextEncoder, TextEncoderStream, TransformStreamDefaultController, URL, URLSearchParams, WebAssembly, WebSocket, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter };
60
- for (const name of web_only_globals_json_1.default) {
61
- Object.defineProperty(DEFAULT_GLOBALS, name, { get: () => { throw new ReferenceError(`${name} is not defined`); } });
62
- }
45
+ const DEFAULT_GLOBALS = Object.defineProperties({}, Object.fromEntries(web_only_globals_json_1.default.map((name) => [name, { get() { throw new ReferenceError(`${name} is not defined`); } }])));
46
+ const BUILTIN_MODULES = [
47
+ ['os', module_os],
48
+ ['process', module_process],
49
+ ['querystring', module_querystring],
50
+ ['punycode', module_punycode],
51
+ ];
52
+ const DEFAULT_ENV = {
53
+ PATH: '/usr/local/bin:/usr/bin:/bin',
54
+ SHLVL: '1',
55
+ SHELL: '/bin/bash',
56
+ TERM: 'none',
57
+ PS1: '',
58
+ PS2: '> ',
59
+ HISTFILE: '~/.bash_history',
60
+ EDITOR: 'vim',
61
+ VISUAL: 'vim',
62
+ LANG: 'en_US.utf8',
63
+ HOSTNAME: 'fake-node',
64
+ TMPDIR: '/tmp',
65
+ };
63
66
  class Process {
64
67
  fakeNode;
65
68
  pid;
69
+ priority = 0;
70
+ uid = 0;
71
+ gid = 0;
72
+ groups = [];
73
+ cwd;
74
+ umask = 0o6440;
66
75
  argv = [];
67
76
  argv0 = '';
77
+ execArgv = [];
78
+ execArgv0 = '/usr/bin/local/node';
79
+ path;
68
80
  module;
69
81
  code;
70
- path;
71
82
  constructor(fakeNode, { path = '', code, module }) {
72
83
  this.fakeNode = fakeNode;
73
84
  this.pid = fakeNode.nextPid;
@@ -75,12 +86,16 @@ class Process {
75
86
  fakeNode.processes.set(this.pid, this);
76
87
  this.code = code;
77
88
  this.path = path;
89
+ this.cwd = path.split('/').slice(0, -1).join('/');
78
90
  this.module = module ?? false;
79
91
  }
92
+ get env() {
93
+ return this.fakeNode.getenv(this.pid);
94
+ }
80
95
  run() {
81
96
  let code;
82
97
  if (this.module) {
83
- code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){__fakeNode_process__.fakeNode.modules.set('${this.module},(function(){${this.code};return module.exports;})());}`;
98
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){__fakeNode__.modules.set('${this.module},(function(){${this.code};return module.exports;})());}`;
84
99
  }
85
100
  else {
86
101
  code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){(function(){${this.code}})();}`;
@@ -92,49 +107,37 @@ class Process {
92
107
  }
93
108
  exports.Process = Process;
94
109
  class FakeNode {
110
+ version = '0.3.0';
95
111
  static nextId = 0;
96
112
  id;
97
113
  globalName;
114
+ globalenv = DEFAULT_ENV;
98
115
  modules = new Map();
99
- builtinModules = new Map([
100
- ['assert', assert_1.default],
101
- ['buffer', module_buffer],
102
- ['path', module_path],
103
- ['punycode', module_punycode],
104
- ['querystring', module_querystring],
105
- ['readline', module_readline],
106
- ['stream', module_stream],
107
- ['string_decoder', module_string_decoder],
108
- ['test', module_test],
109
- ['url', module_url],
110
- ['util', module_util],
111
- ]);
112
116
  globals;
113
117
  processes = new Map();
114
118
  nextPid = 3;
115
119
  window = window;
120
+ errorCallbacks = [];
116
121
  constructor() {
117
122
  this.id = FakeNode.nextId;
118
123
  FakeNode.nextId++;
119
124
  this.globalName = '__fakeNode_' + this.id + '__';
120
125
  // @ts-ignore
121
126
  globalThis[this.globalName] = this;
122
- this.globals = Object.create(DEFAULT_GLOBALS);
123
- Object.assign(this.globals, { require: this.require, Buffer: module_buffer.Buffer });
127
+ this.globals = { __fakeNode__: this };
128
+ Object.assign(this.globals, DEFAULT_GLOBALS);
129
+ window.addEventListener('error', ({ error }) => this.onError(error));
130
+ window.addEventListener('unhandledrejection', ({ reason }) => reason instanceof Error ? this.onError(reason) : this.onError(new Error(String(reason))));
131
+ for (const [name, module] of BUILTIN_MODULES) {
132
+ this.addModuleFromValue(name, module);
133
+ this.addModuleFromValue('node:' + name, module);
134
+ this.addModuleFromValue('fake-node:' + name, module);
135
+ }
124
136
  }
125
137
  require(module) {
126
- if (module.startsWith('fake-node:')) {
127
- module = module.slice('fake-node:'.length);
128
- }
129
- else if (module.startsWith('node:')) {
130
- module = module.slice('node:'.length);
131
- }
132
138
  if (this.modules.has(module)) {
133
139
  return this.modules.get(module);
134
140
  }
135
- else if (this.builtinModules.has(module)) {
136
- return this.builtinModules.get(module);
137
- }
138
141
  else {
139
142
  throw new Error(`cannot find module '${module}'`);
140
143
  }
@@ -144,10 +147,12 @@ class FakeNode {
144
147
  if (process === undefined) {
145
148
  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.`);
146
149
  }
147
- let scope = Object.create(this.globals);
150
+ let scope = {};
151
+ Object.assign(scope, this.globals);
148
152
  scope.global = scope;
149
153
  scope.globalThis = scope;
150
154
  scope.__fakeNode_process__ = process;
155
+ scope.require = this.require.bind(this);
151
156
  if (process.path !== '') {
152
157
  const pathParts = process.path.split('/');
153
158
  scope.__dirname = pathParts.slice(0, -1).join('/');
@@ -155,17 +160,76 @@ class FakeNode {
155
160
  }
156
161
  if (process.module !== false) {
157
162
  scope.module = {
158
- exports: {}
163
+ exports: {},
159
164
  };
165
+ // @ts-ignore
160
166
  scope.exports = scope.module.exports;
161
167
  }
162
168
  return scope;
163
169
  }
170
+ getenv(pid) {
171
+ let env = Object.create(this.globalenv);
172
+ const process = this.processes.get(pid);
173
+ if (process === undefined) {
174
+ throw new TypeError(`invalid PID: ${pid}`);
175
+ }
176
+ env.USER = this.getUserFromUID(process.uid);
177
+ return env;
178
+ }
164
179
  run(code) {
165
180
  (new Process(this, { code, path: '/' })).run();
166
181
  }
167
182
  addModule(name, code) {
168
183
  (new Process(this, { code, path: '/', module: name })).run();
169
184
  }
185
+ addModuleFromValue(name, module) {
186
+ this.modules.set(name, module);
187
+ }
188
+ getUserFromUID(uid) {
189
+ if (typeof uid === 'string') {
190
+ return uid;
191
+ }
192
+ else {
193
+ return 'root';
194
+ }
195
+ }
196
+ getUserFromGID(gid) {
197
+ if (typeof gid === 'string') {
198
+ return gid;
199
+ }
200
+ else {
201
+ return 'root';
202
+ }
203
+ }
204
+ getUIDFromUser(user) {
205
+ if (typeof user === 'number') {
206
+ return user;
207
+ }
208
+ else {
209
+ return 0;
210
+ }
211
+ }
212
+ getGIDFromGroup(group) {
213
+ if (typeof group === 'number') {
214
+ return group;
215
+ }
216
+ else {
217
+ return 0;
218
+ }
219
+ }
220
+ onError(error) {
221
+ for (const callback of this.errorCallbacks) {
222
+ if (callback !== undefined) {
223
+ callback(error);
224
+ }
225
+ }
226
+ }
227
+ addErrorCallback(callback) {
228
+ this.errorCallbacks.push(callback);
229
+ return this.errorCallbacks.length - 1;
230
+ }
231
+ removeErrorCallback(callbackID) {
232
+ this.errorCallbacks[callbackID] = undefined;
233
+ }
170
234
  }
171
235
  exports.FakeNode = FakeNode;
package/lib/os.d.ts ADDED
@@ -0,0 +1,191 @@
1
+ export declare const EOL = "\n";
2
+ export declare function availableParallelism(): number;
3
+ export declare function arch(): string;
4
+ declare enum signals {
5
+ SIGHUP = 1,
6
+ SIGINT = 2,
7
+ SIGQUIT = 3,
8
+ SIGILL = 4,
9
+ SIGTRAP = 5,
10
+ SIGABRT = 6,
11
+ SIGIOT = 6,
12
+ SIGBUS = 7,
13
+ SIGFPE = 8,
14
+ SIGKILL = 9,
15
+ SIGUSR1 = 10,
16
+ SIGUSR2 = 11,
17
+ SIGSEGV = 12,
18
+ SIGPIPE = 13,
19
+ SIGALRM = 14,
20
+ SIGTERM = 15,
21
+ SIGCHLD = 16,
22
+ SIGSTKFLT = 17,
23
+ SIGCONT = 18,
24
+ SIGSTOP = 19,
25
+ SIGTSTP = 20,
26
+ SIGBREAK = 21,
27
+ SIGTTIN = 22,
28
+ SIGTTOU = 23,
29
+ SIGURG = 24,
30
+ SIGXCPU = 25,
31
+ SIGXFSZ = 26,
32
+ SIGVTALRM = 27,
33
+ SIGPROF = 28,
34
+ SIGWINCH = 29,
35
+ SIGIO = 30,
36
+ SIGPOLL = 30,
37
+ SIGLOST = 31,
38
+ SIGPWR = 32,
39
+ SIGINFO = 32,
40
+ SIGSYS = 33,
41
+ SIGUNUSED = 33
42
+ }
43
+ declare enum errno {
44
+ E2BIG = 0,
45
+ EACCES = 1,
46
+ EADDRINUSE = 2,
47
+ EADDRNONOTAVAIL = 3,
48
+ EAFNOSUPPORT = 4,
49
+ EAGAIN = 5,
50
+ EALREADY = 6,
51
+ EBADF = 7,
52
+ EBADMSG = 8,
53
+ EBUSY = 9,
54
+ ECANCELED = 10,
55
+ ECHILD = 11,
56
+ ECONNABORTED = 12,
57
+ ECONNREFUSED = 13,
58
+ ECONNRESET = 14,
59
+ EDEADLK = 15,
60
+ EDESTADDRREQ = 16,
61
+ EDOM = 17,
62
+ EDQUOT = 18,
63
+ EEXIST = 19,
64
+ EFAULT = 20,
65
+ EFBIG = 21,
66
+ EHOSTUNREACH = 22,
67
+ EIDRM = 23,
68
+ EILSEQ = 24,
69
+ EINPROGRESS = 25,
70
+ EINTR = 26,
71
+ EINVAL = 27,
72
+ EIO = 28,
73
+ EISCONN = 29,
74
+ EISDIR = 30,
75
+ ELOOP = 31,
76
+ EMFILE = 32,
77
+ EMLINK = 33,
78
+ EMGSIZE = 34,
79
+ EMULTIHOP = 35,
80
+ ENAMETOOLONG = 36,
81
+ ENETDOWN = 37,
82
+ ENETRESET = 38,
83
+ ENETUNREACH = 39,
84
+ ENFILE = 40,
85
+ ENOBUFS = 41,
86
+ ENODATA = 42,
87
+ ENODEV = 43,
88
+ ENOENT = 44,
89
+ ENOEXEC = 45,
90
+ ENOLCK = 46,
91
+ ENOLINK = 47,
92
+ ENOMEM = 48,
93
+ ENOMSG = 49,
94
+ ENOPROTOOPT = 50,
95
+ ENOSPC = 51,
96
+ ENOSR = 52,
97
+ ENOSTR = 53,
98
+ ENOSYS = 54,
99
+ ENOTCONN = 55,
100
+ ENOTDIR = 56,
101
+ ENOTEMPTY = 57,
102
+ ENOTSOCK = 58,
103
+ ENOTSUP = 59,
104
+ ENOTTY = 60,
105
+ ENXIO = 61,
106
+ EOPNOTSUPP = 62,
107
+ EOVERFLOW = 63,
108
+ EPERM = 64,
109
+ EPIPE = 65,
110
+ EPROTO = 66,
111
+ EPROTONOSUPPORT = 67,
112
+ EPROTOTYPE = 68,
113
+ ERANGE = 69,
114
+ EROFS = 70,
115
+ ESPIPE = 71,
116
+ ESRCH = 72,
117
+ ESTALE = 73,
118
+ ETIME = 74,
119
+ ETIMEDOUT = 75,
120
+ ETXTBSY = 76,
121
+ EWOULDBLOCK = 77,
122
+ EXDEV = 78
123
+ }
124
+ declare enum dlopen {
125
+ RTLD_LAZY = 1,
126
+ RTLD_NOW = 2,
127
+ RTLD_GLOBAL = 3,
128
+ RTLD_LOCAL = 4,
129
+ RTLD_DEEPBIND = 5
130
+ }
131
+ declare enum priority {
132
+ PRIORITY_LOW = 1,
133
+ PRIORITY_BELOW_NORMAL = 2,
134
+ PRIORITY_NORMAL = 3,
135
+ PRIORITY_ABOVE_NORMAL = 4,
136
+ PRIORITY_HIGH = 5,
137
+ PRIORITY_HIGHEST = 6
138
+ }
139
+ export declare const constants: {
140
+ signals: typeof signals;
141
+ errno: typeof errno;
142
+ dlopen: typeof dlopen;
143
+ priority: typeof priority;
144
+ };
145
+ export declare function cpus(): {
146
+ model: string;
147
+ speed: number;
148
+ times: {
149
+ user: number;
150
+ nice: number;
151
+ sys: number;
152
+ idle: number;
153
+ irq: number;
154
+ };
155
+ }[];
156
+ export declare const devNull = "/dev/null";
157
+ export declare function endianness(): string;
158
+ export declare function freemem(): number;
159
+ export declare function getPriority(pid?: number): number;
160
+ export declare function homedir(): string;
161
+ export declare function hostname(): string;
162
+ export declare function loadavg(): [number, number, number];
163
+ export declare function machine(): string;
164
+ export declare function networkInterfaces(): {
165
+ [key: string]: {
166
+ address: string;
167
+ netmask: string;
168
+ family: 'IPV4' | 'IPV6';
169
+ mac: string;
170
+ internal: boolean;
171
+ scopeid: number;
172
+ cidr: string;
173
+ };
174
+ };
175
+ export declare function platform(): string;
176
+ export declare function release(): string;
177
+ export declare function setPriority(priority: number): void;
178
+ export declare function setPriority(pid: number, priority: number): void;
179
+ export declare function tmpdir(): string;
180
+ export declare function totalmem(): number;
181
+ export declare function type(): string;
182
+ export declare function uptime(): number;
183
+ export declare function userInfo(): {
184
+ username: string;
185
+ uid: number;
186
+ gid: number;
187
+ shell: string;
188
+ homedir: string;
189
+ };
190
+ export declare function version(): string;
191
+ export {};