fake-node 0.1.0 → 0.2.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/index.js CHANGED
@@ -1 +1,171 @@
1
- throw new ReferenceError('module is not defined');
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
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"));
57
+ 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
+ }
63
+ class Process {
64
+ fakeNode;
65
+ pid;
66
+ argv = [];
67
+ argv0 = '';
68
+ module;
69
+ code;
70
+ path;
71
+ constructor(fakeNode, { path = '', code, module }) {
72
+ this.fakeNode = fakeNode;
73
+ this.pid = fakeNode.nextPid;
74
+ fakeNode.nextPid++;
75
+ fakeNode.processes.set(this.pid, this);
76
+ this.code = code;
77
+ this.path = path;
78
+ this.module = module ?? false;
79
+ }
80
+ run() {
81
+ let code;
82
+ 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;})());}`;
84
+ }
85
+ else {
86
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){(function(){${this.code}})();}`;
87
+ }
88
+ let elt = document.createElement('script');
89
+ elt.textContent = code;
90
+ document.body.appendChild(elt);
91
+ }
92
+ }
93
+ exports.Process = Process;
94
+ class FakeNode {
95
+ static nextId = 0;
96
+ id;
97
+ globalName;
98
+ 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
+ globals;
113
+ processes = new Map();
114
+ nextPid = 3;
115
+ window = window;
116
+ constructor() {
117
+ this.id = FakeNode.nextId;
118
+ FakeNode.nextId++;
119
+ this.globalName = '__fakeNode_' + this.id + '__';
120
+ // @ts-ignore
121
+ globalThis[this.globalName] = this;
122
+ this.globals = Object.create(DEFAULT_GLOBALS);
123
+ Object.assign(this.globals, { require: this.require, Buffer: module_buffer.Buffer });
124
+ }
125
+ 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
+ if (this.modules.has(module)) {
133
+ return this.modules.get(module);
134
+ }
135
+ else if (this.builtinModules.has(module)) {
136
+ return this.builtinModules.get(module);
137
+ }
138
+ else {
139
+ throw new Error(`cannot find module '${module}'`);
140
+ }
141
+ }
142
+ getGlobals(pid) {
143
+ const process = this.processes.get(pid);
144
+ if (process === undefined) {
145
+ 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
+ }
147
+ let scope = Object.create(this.globals);
148
+ scope.global = scope;
149
+ scope.globalThis = scope;
150
+ scope.__fakeNode_process__ = process;
151
+ if (process.path !== '') {
152
+ const pathParts = process.path.split('/');
153
+ scope.__dirname = pathParts.slice(0, -1).join('/');
154
+ scope.__filename = pathParts[pathParts.length - 1];
155
+ }
156
+ if (process.module !== false) {
157
+ scope.module = {
158
+ exports: {}
159
+ };
160
+ scope.exports = scope.module.exports;
161
+ }
162
+ return scope;
163
+ }
164
+ run(code) {
165
+ (new Process(this, { code, path: '/' })).run();
166
+ }
167
+ addModule(name, code) {
168
+ (new Process(this, { code, path: '/', module: name })).run();
169
+ }
170
+ }
171
+ exports.FakeNode = FakeNode;
package/index.ts CHANGED
@@ -1,80 +1,148 @@
1
1
 
2
- import globals from './globals';
3
-
4
- import * as module_assert from './modules/assert';
5
- import * as module_buffer from './modules/buffer';
6
- import * as module_fs from './modules/fs';
7
- import * as module_os from './modules/os';
8
- import * as module_path from './modules/path';
9
- import * as module_process from './modules/process';
10
- import * as module_querystring from './modules/querystring';
11
- import * as module_util from './modules/util';
12
-
13
- function setup(path?: string, argv: string[] = []): object {
14
- module_process._argv.argv = argv;
15
- let scope: {[key: string]: any} = {};
16
- Object.assign(scope, globals);
17
- let readonly: {[key: string]: any} = {};
18
- scope.global = scope;
19
- scope.globalThis = scope;
20
- globalThis.__fakeNode_oldWd = globalThis.__fakeNode_wd;
21
- if (path !== undefined) {
22
- const splitPath = path.split('/');
23
- readonly.__dirname = splitPath.slice(0, -1).join('/');
24
- readonly.__filename = splitPath[splitPath.length - 1];
25
- scope.__fakeNode_wd = readonly.__dirname;
26
- }
27
- Object.defineProperties(scope, Object.fromEntries(Object.entries(readonly).map(([name, value]) => [name, {value: value, writable: false}])));
28
- return scope;
29
- }
2
+ import module_assert from 'assert';
3
+ import * as module_buffer from 'buffer';
4
+ // @ts-ignore
5
+ import * as module_path from 'path';
6
+ import * as module_punycode from 'punycode';
7
+ import * as module_querystring from 'querystring';
8
+ // @ts-ignore
9
+ import * as module_readline from 'readline';
10
+ // @ts-ignore
11
+ import * as module_stream from 'stream';
12
+ // @ts-ignore
13
+ import * as module_string_decoder from 'string_decoder';
14
+ import * as module_test from 'test';
15
+ // @ts-ignore
16
+ import * as module_url from 'url';
17
+ // @ts-ignore
18
+ import * as module_util from 'util';
19
+ import WEB_ONLY_GLOBALS from './web_only_globals.json';
30
20
 
31
- globalThis.__fakeNode_setup = setup;
32
21
 
33
- function cleanup(): void {
34
- globalThis.__fakeNode_wd = globalThis.__fakeNode_oldWd;
22
+ // todo: properly implement eval
23
+ 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};
24
+ for (const name of WEB_ONLY_GLOBALS) {
25
+ Object.defineProperty(DEFAULT_GLOBALS, name, {get: () => {throw new ReferenceError(`${name} is not defined`)}});
35
26
  }
36
27
 
37
- globalThis.__fakeNode_cleanup = cleanup;
38
28
 
39
- function run(code: string, argv: string[] = []): void {
40
- code = `with(window.__fakeNode_setup(undefined,${JSON.stringify(argv)})){(function(){${code}})();window.__fakeNode_cleanup();}`;
41
- let elt = document.createElement('script');
42
- elt.textContent = code;
43
- document.body.appendChild(elt);
44
- }
29
+ export class Process {
45
30
 
46
- function addModule(name: string, code: string): void {
47
- code = `with(window.__fakeNode_setup()){window.__fakeNode_modules.set('${name}',(function(){${code};return module.exports;})();window.__fakeNode_cleanup();}`;
48
- let elt = document.createElement('script');
49
- elt.textContent = code;
50
- document.body.appendChild(elt);
51
- }
31
+ fakeNode: FakeNode;
32
+ pid: number;
33
+ argv: string[] = [];
34
+ argv0: string = '';
35
+ module: false | string;
36
+ code: string;
37
+ path: string;
52
38
 
53
- function addBuiltinModule(name: string, data: any): void {
54
- globalThis.__fakeNode_builtinModules.set(name, data);
55
- }
39
+ constructor(fakeNode: FakeNode, {path = '', code, module}: {path?: string, code: string, module?: false | string}) {
40
+ this.fakeNode = fakeNode;
41
+ this.pid = fakeNode.nextPid;
42
+ fakeNode.nextPid++;
43
+ fakeNode.processes.set(this.pid, this);
44
+ this.code = code;
45
+ this.path = path;
46
+ this.module = module ?? false;
47
+ }
56
48
 
57
- function deleteModule(name: string): void {
58
- globalThis.__fakeNode_modules.delete(name);
59
- }
49
+ run(): void {
50
+ let code: string;
51
+ if (this.module) {
52
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){__fakeNode_process__.fakeNode.modules.set('${this.module},(function(){${this.code};return module.exports;})());}`;
53
+ } else {
54
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){(function(){${this.code}})();}`;
55
+ }
56
+ let elt = document.createElement('script');
57
+ elt.textContent = code;
58
+ document.body.appendChild(elt);
59
+ }
60
60
 
61
- function deleteBuiltinModule(name: string): void {
62
- globalThis.__fakeNode_builtinModules.delete(name);
63
61
  }
64
62
 
65
- addBuiltinModule('assert', module_assert);
66
- addBuiltinModule('buffer', module_buffer);
67
- addBuiltinModule('fs', module_fs);
68
- addBuiltinModule('os', module_os);
69
- addBuiltinModule('path', module_path);
70
- addBuiltinModule('process', module_process);
71
- addBuiltinModule('querystring', module_querystring);
72
- addBuiltinModule('util', module_util);
73
-
74
- export {
75
- run,
76
- addModule,
77
- addBuiltinModule,
78
- deleteModule,
79
- deleteBuiltinModule,
63
+
64
+ export class FakeNode {
65
+
66
+ static nextId: number = 0;
67
+ id: number;
68
+ globalName: string;
69
+
70
+ modules: Map<string, any> = new Map();
71
+ builtinModules: Map<string, any> = new Map<string, any>([
72
+ ['assert', module_assert],
73
+ ['buffer', module_buffer],
74
+ ['path', module_path],
75
+ ['punycode', module_punycode],
76
+ ['querystring', module_querystring],
77
+ ['readline', module_readline],
78
+ ['stream', module_stream],
79
+ ['string_decoder', module_string_decoder],
80
+ ['test', module_test],
81
+ ['url', module_url],
82
+ ['util', module_util],
83
+ ]);
84
+
85
+ globals: {[key: string]: any};
86
+
87
+ processes: Map<number, Process> = new Map();
88
+ nextPid: number = 3;
89
+
90
+ window: Window = window;
91
+
92
+ constructor() {
93
+ this.id = FakeNode.nextId;
94
+ FakeNode.nextId++;
95
+ this.globalName = '__fakeNode_' + this.id + '__';
96
+ // @ts-ignore
97
+ globalThis[this.globalName] = this;
98
+ this.globals = Object.create(DEFAULT_GLOBALS);
99
+ Object.assign(this.globals, {require: this.require, Buffer: module_buffer.Buffer});
100
+ }
101
+
102
+ require(module: string): any {
103
+ if (module.startsWith('fake-node:')) {
104
+ module = module.slice('fake-node:'.length);
105
+ } else if (module.startsWith('node:')) {
106
+ module = module.slice('node:'.length);
107
+ }
108
+ if (this.modules.has(module)) {
109
+ return this.modules.get(module);
110
+ } else if (this.builtinModules.has(module)) {
111
+ return this.builtinModules.get(module);
112
+ } else {
113
+ throw new Error(`cannot find module '${module}'`);
114
+ }
115
+ }
116
+
117
+ getGlobals(pid: number): object {
118
+ const process = this.processes.get(pid);
119
+ if (process === undefined) {
120
+ 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.`);
121
+ }
122
+ let scope: {[key: string]: any} = Object.create(this.globals);
123
+ scope.global = scope;
124
+ scope.globalThis = scope;
125
+ scope.__fakeNode_process__ = process;
126
+ if (process.path !== '') {
127
+ const pathParts = process.path.split('/');
128
+ scope.__dirname = pathParts.slice(0, -1).join('/');
129
+ scope.__filename = pathParts[pathParts.length - 1];
130
+ }
131
+ if (process.module !== false) {
132
+ scope.module = {
133
+ exports: {}
134
+ };
135
+ scope.exports = scope.module.exports;
136
+ }
137
+ return scope;
138
+ }
139
+
140
+ run(code: string): void {
141
+ (new Process(this, {code, path: '/'})).run();
142
+ }
143
+
144
+ addModule(name: string, code: string): void {
145
+ (new Process(this, {code, path: '/', module: name})).run();
146
+ }
147
+
80
148
  }
package/package.json CHANGED
@@ -1,14 +1,39 @@
1
1
  {
2
2
  "name": "fake-node",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A fake version of Node that works in the browser",
5
5
  "license": "MIT",
6
6
  "author": "speedydelete",
7
- "type": "module",
7
+ "type": "commonjs",
8
8
  "main": "index.js",
9
9
  "homepage": "https://github.com/speedydelete/fake-node",
10
- "repository": "github:speedydelete/fake-node",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/speedydelete/fake-node.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/speedydelete/fake-node/issues"
16
+ },
11
17
  "scripts": {
12
- "test": "echo \"Error: no test specified\" && exit 1"
18
+ "test": "echo \"Error: no test specified\" && exit 1",
19
+ "build": "tsc"
20
+ },
21
+ "dependencies": {
22
+ "assert": "^2.1.0",
23
+ "buffer": "^6.0.3",
24
+ "path": "^0.12.7",
25
+ "punycode": "^2.3.1",
26
+ "querystring": "^0.2.1",
27
+ "readline": "^1.3.0",
28
+ "stream": "^0.0.3",
29
+ "string_decoder": "^1.3.0",
30
+ "test": "^3.3.0",
31
+ "url": "^0.11.4",
32
+ "util": "^0.12.5"
33
+ },
34
+ "devDependencies": {
35
+ "@types/assert": "^1.5.11",
36
+ "@types/punycode": "^2.1.4",
37
+ "typescript": "^5.7.3"
13
38
  }
14
39
  }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "resolveJsonModule": true,
5
+ "esModuleInterop": true,
6
+ "module": "NodeNext"
7
+ },
8
+ "files": ["index.ts"],
9
+ "exclude": ["node_modules"]
10
+ }